浅析深度学习(四)--图片分类回归实战

目标:通过11个类别的训练进行图片分类预测(本文不做测试集)

训练集,验证集

一.调包

import torch
from torch.utils.data import Dataset,DataLoader
import random
import numpy as np
import os
from PIL import Image
from tqdm import tqdm
from torchvision.transforms import transforms
import torch.nn as nn
import time
import matplotlib.pyplot as plt

二.数据增广

通过自由调整大小和颜色,识别更多样同个图片

同个图片调整大小,颜色

#图片的数据增广
train_transformer = transforms.Compose([
    transforms.ToPILImage(),  # 这个img 转为PIL
    transforms.RandomResizedCrop(224),  #随机resize 。 取中间的224.
    transforms.ToTensor()          # 转为张量

])

设下种子,让代码每次运行结果一样

#直接复制
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)
#################################################################
seed_everything(0)   # 让代码每次运行结果一样,
########################

#######读数据。
HW = 224

三.创建函数--读文件

文件夹内数据

def read_file(path):
    #共11个类别
    for i in tqdm(range(11)):       #tqdm为进度条函数,能给出进度条
        img_path = path + "/%02d/"%i
        img_list = os.listdir(img_path) # 读取文件夹下所有文件
        #初始化xi yi
        xi = np.zeros((len(img_list), HW, HW, 3), dtype=np.uint8)  #共280 个 224* 224 *3
        yi = np.zeros(len(img_list), dtype=np.uint8)# 280*1
        for j, img in enumerate(img_list):  #j是下标0.1.2.3...,img是内容0276.0277....
            true_img_path = img_path + img
            img = Image.open(true_img_path)     #打开图片
            img = img.resize((HW,HW))       # 所有图片都要转为224*224(HW*HW)
            #输入数据
            xi[j, ...] = img        #列下标为j,行下标随便取
            yi[j] = i
        #第一次读数据
        if i == 0:
            X = xi
            Y = yi
        #之后就是不断合并Xi
        else:
            #concatenate是合并
            X = np.concatenate((X, xi), axis=0)
            Y = np.concatenate((Y, yi), axis=0)
    print("读取了%d个数据"%len(Y))
    return  X, Y

四.创建类--数据集

#数据集
class fooddataset(Dataset):
    def __init__(self, path):
        #要调整用super
        super(fooddataset, self).__init__()
        #读文件
        self.X, self.Y = read_file(path)
        # 只要是标签就用longtensor格式
        self.Y = torch.LongTensor(self.Y)
        #数据增广
        self.transformer = train_transformer

    def __getitem__(self, item):
        #返回值为x的数据增广和y标签
        return self.transformer(self.X[item]), self.Y[item]

    def __len__(self):
        return len(self.Y)

#设置路径
train_set = fooddataset(r"D:\深度学习\分类实战\food\food-11_sample\training\labeled")
val_set = fooddataset(r"D:\深度学习\分类实战\food\food-11_sample\validation")
#将数据装入loader 方便取一个batch的数据
train_loader = DataLoader(train_set, batch_size=4)
val_loader = DataLoader(val_set, batch_size=4)

五.创建类--模型

class myModel(nn.Module):
    def __init__(self):
        super(myModel, self).__init__()
        #3*224*224 - 512*7*7
        self.layer0 = nn.Sequential(
            #卷积
            nn.Conv2d(3, 64, 3, 1, 1),
            #归一化
            nn.BatchNorm2d(64),
            #激活函数
            nn.ReLU(),
            #最大池化pooling
            nn.MaxPool2d(2)
        )  # Sequential把里面的操作合成一个————64*112*112

        self.layer1 = nn.Sequential(
            nn.Conv2d(64, 128, 3, 1, 1),
            nn.BatchNorm2d(128),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )  # 把里面的操作合成一个    128*56*56

        self.layer2 = nn.Sequential(
            nn.Conv2d(128, 256, 3, 1, 1),
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )  # 把里面的操作合成一个    256*28*28

        self.layer3 = nn.Sequential(
            nn.Conv2d(256, 512, 3, 1, 1),
            nn.BatchNorm2d(512),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )  # 把里面的操作合成一个    512*14*14
        self.pool1 = nn.MaxPool2d(2) #512*7*7
        #拉直为25088
        self.fc1 = nn.Linear(25088, 1000)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(1000, 11)
    #前向过程
    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.view
        x = x.view(x.size()[0], -1)
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

六.设置参数

权重缩减:通过降低w,使曲线更加平滑

mymodel = myModel()
#
# for data in train_loader:
#     print(data)
#     x, y = data[0], data[1]
#     out = mymodel(x)


lr = 0.001
loss = nn.CrossEntropyLoss()    #分类专用loss
epochs = 20 #20轮
# AdamW  weight_dacay权重缩减
optimizer = torch.optim.AdamW(mymodel.parameters(), lr=lr, weight_decay=1e-4)             
device = 'cuda' if torch.cuda.is_available() else 'cpu'         #设备
save_ = 'model_save/mymodel.pth'        #保存路径

七.开始训练

#万能的训练代码
def train_val(model, trainloader, valloader,optimizer, loss, epoch, device, save_):
    # trainloader = DataLoader(trainset,batch_size=batch,shuffle=True)
    # valloader = DataLoader(valset,batch_size=batch,shuffle=True)
    model = model.to(device)                # 模型和数据 ,要在一个设备上。  cpu - gpu
    plt_train_loss = []
    plt_val_loss = []


    val_rel = []
    min_val_loss = 100000                 # 记录训练验证loss 以及验证loss和结果

    for i in range(epoch):                 # 训练epoch 轮
        train_acc = 0.0
        val_acc = 0.0
        start_time = time.time()             # 记录开始时间
        model.train()                         # 模型设置为训练状态      结构
        train_loss = 0.0
        val_loss = 0.0
        for data in trainloader:                     # 从训练集取一个batch的数据
            optimizer.zero_grad()                   # 梯度清0
            x, target = data[0].to(device), data[1].to(device)       # 将数据放到设备上
            pred = model(x)                          # 用模型预测数据
            bat_loss = loss(pred, target)       # 计算loss
            bat_loss.backward()                        # 梯度回传, 反向传播。
            optimizer.step()                            #用优化器更新模型。  轮到SGD出手了
            train_loss += bat_loss.detach().cpu().item()             #记录loss和
            train_acc += np.sum(np.argmax(pred.cpu().data.numpy(), axis=1) == data[1].cpu().numpy())

        plt_train_loss. append(train_loss/trainloader.dataset.__len__())   #记录loss到列表。注意是平均的loss ,因此要除以数据集长度。

        model.eval()                 # 模型设置为验证状态
        with torch.no_grad():                    # 模型不再计算梯度
            for data in valloader:                      # 从验证集取一个batch的数据
                val_x , val_target = data[0].to(device), data[1].to(device)          # 将数据放到设备上
                val_pred = model(val_x)                 # 用模型预测数据
                val_bat_loss = loss(val_pred, val_target)          # 计算loss
                val_loss += val_bat_loss.detach().cpu().item()                  # 计算loss
                val_rel.append(val_pred)                 #记录预测结果
        if val_loss < min_val_loss:
            torch.save(model, save_)               #如果loss比之前的最小值小, 说明模型更优, 保存这个模型
        val_acc += np.sum(np.argmax(val_pred.cpu().data.numpy(), axis=1) == val_target[1].cpu().numpy())    #argmax为最大值的下标
        print("val_acc:",val_acc)
        plt_val_loss.append(val_loss/valloader.dataset.__len__())  #记录loss到列表。注意是平均的loss ,因此要除以数据集长度。
        #
        print('[%03d/%03d] %2.2f sec(s) TrainLoss : %.6f | valLoss: %.6f' % \
              (i, epoch, time.time()-start_time, plt_train_loss[-1], plt_val_loss[-1])
              )              #打印训练结果。 注意python语法, %2.2f 表示小数位为2的浮点数, 后面可以对应。

        # print('[%03d/%03d] %2.2f sec(s) TrainLoss : %3.6f | valLoss: %.6f' % \
        #       (i, epoch, time.time()-start_time, 2210.2255411, plt_val_loss[-1])
        #       )              #打印训练结果。 注意python语法, %2.2f 表示小数位为2的浮点数, 后面可以对应。
    plt.plot(plt_train_loss)              # 画图, 向图中放入训练loss数据
    plt.plot(plt_val_loss)                # 画图, 向图中放入训练loss数据
    plt.title('loss')                      # 画图, 标题
    plt.legend(['train', 'val'])             # 画图, 图例
    plt.show()                                 # 画图, 展示


train_val(mymodel, train_loader, val_loader,optimizer, loss, epochs, device, save_)
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
docker-compose 是 Docker 官方的一个用于定义和运行容器化应用的工具。它使用 YAML 文件来配置应用的服务、网络和卷等方面的设置。 当使用 docker-compose 部署 MySQL 时,可能会遇到无法访问 MySQL 的问题。出现这种情况一般有以下几个可能的原因: 1. 网络配置问题:docker-compose 在默认情况下会创建一个默认的网络,并将所有定义的服务连接到该网络。如果服务的网络配置不正确,可能导致无法访问 MySQL。可以通过检查网络配置或创建自定义网络来解决此问题。 2. 端口映射问题:MySQL 默认使用 3306 端口进行通信,但是在容器内部的端口与宿主机上的端口之间可能存在映射问题。可以通过检查端口映射配置或使用容器的 IP 地址来解决此问题。 3. 认证问题:MySQL 服务通常需要进行身份验证才能访问。在 docker-compose 文件中,可以通过设置环境变量来指定 MySQL 的用户名和密码。如果未正确设置这些环境变量,可能导致无法访问 MySQL。可以检查环境变量配置或者在容器内部手动配置用户名和密码来解决此问题。 4. 容器启动顺序问题:如果在 docker-compose 文件中定义了多个服务,并且它们之间有依赖关系,那么容器启动的顺序可能会影响 MySQL 的访问。可以通过在容器之间添加依赖或者设置延迟启动来解决此问题。 总结起来,当 docker-compose 部署的 MySQL 无法访问时,通常是由于网络配置、端口映射、认证配置或容器启动顺序等问题造成的。通过检查这些配置,并进行适当的调整或修复,通常可以解决无法访问 MySQL 的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值