今天学习的是第五节上 图像分类实战——食物分类
目的:通过模型预测图片是哪类食物
引用包:
import random
import torch
import torch.nn as nn
import numpy as np
import os
from PIL import Image #读取文件数据
from torch.utils.data import Dataset, DataLoader
from tqdm import tqdm #查看读取进度
seed_everything()函数:
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 #深度学习领域一般让图片大小为224,而文件中的图片是512*512
#读文件
def read_file(path):
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 #...表示后面的维度表示一致,把图片放到第j个
yi[j] = i #标签
# 把所有的xi,yi在0维合并
if i == 0:
X = xi
Y = yi
else:
X = np.concatenate((X, xi), axis=0)
Y = np.concatenate((Y, yi), axis=0)
print("读到了%d个数据"%len(Y))
return X,Y
数据集:
数据增广(Data Augmentation)
是一种在机器学习和数据分析中广泛使用的技术,主要用于通过对原始数据进行各种转换或操作来增加数据量,从而改善模型的训练效果,尤其是在数据较少时。数据增广的目的是通过人工扩展数据集,增加模型对不同情况的泛化能力,进而提升其预测准确性和鲁棒性。
通俗来说,就是计算机对于同一图片不同尺寸、角度的形式识别不出来,因此全部看作训练集。即一张图片变为表现形式不同的图片进行训练。一般在取数据的时候进行增广
在计算机视觉领域,数据增广技术尤其常见,以下是一些常用的增广技术:
- 旋转:随机旋转图像一定角度,例如从-30度到+30度之间。
- 裁剪:对图像进行随机裁剪,改变图像的大小或缩放比例。
- 翻转:例如水平翻转或垂直翻转图像。
- 颜色变换:调整图像的亮度、对比度、饱和度或色调等。
- 缩放:对图像进行放大或缩小。
- 加噪声:在图像中加入随机噪声,模拟不同的拍摄环境。
透视变换(仿射变换):通过透视或仿射变换来模拟不同的视角。
数据变换
训练集和验证集的数据变换不同,验证和测试的时候要用原图,训练的时候才需要不同的数据变换进行训练
#数据变换
train_transform = transforms.Compose(
[
transforms.ToPILImage(), #图片为224*224*3,模型需要3*224*224
transforms.RandomResizedCrop(224), #对图片随机放大裁切
transforms.RandomRotation(50), #对图片50°以内随机旋转
transforms.ToTensor() #变为张量进行模型运行
]
)
val_transform = transforms.Compose(
[
transforms.ToPILImage(), #图片为224*224*3,模型需要3*224*224
transforms.ToTensor() #变为张量进行模型运行
]
)
模型
#模型
class myModel(nn.Module):
def __init__(self, num_class): #搭建模型框架
super(myModel, self).__init__()
#图片输入为3*224*224,要变为512*7*7,然后拉直、全连接、分类
self.conv1 = nn.Conv2d(3, 64, 3, 1, 1) #64*224*224
self.bn1 = nn.BatchNorm2d(64) #归一化
self.relu = nn.ReLU()
self.pool1 = nn.MaxPool2d(2) #64*112*112
self.layer1 = nn.Sequential( #这样合并更方便,且美观
nn.Conv2d(64, 128, 3, 1, 1), #128*112*112
nn.BatchNorm2d(128), #归一化
nn.ReLU(),
nn.MaxPool2d(2) #127*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.pool2 = nn.MaxPool2d(2) #512*7*7
self.fc1 = nn.Linear(25088, 1000) #卷积 25088->1000
self.relu2 = nn.ReLU()
self.fc2 = nn.Linear(1000, num_class) #1000->num_class(11)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.pool1(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.pool2(x)
x = x.view(x.size()[0], -1) #拉直
x = self.fc1(x)
x = self.relu2(x)
x = self.fc2(x)
return x
6565



被折叠的 条评论
为什么被折叠?



