数据集
训练集有带标签的数据和不带标签的数据,一共11钟食物,每一种280张图片
验证集每一种30张,无标签
训练集3327张
数据预处理——从文件夹里读出图片
1.训练集有标签数据,遍历11个类别文件夹,得到各280张图片的完整路径
2.用image的函数将目标路径的图片转换为rgb图片形式
3.创建两个numpy数组,将每一个224*224*3的图片以及其标签分别存入数组,一共11个280张图片数组竖向拼接成一个大的数组
# 读取文件的图片
def read_file(path):
for i in tqdm(range(11)): # 遍历一共11个文件夹,tqdm就是运行的时候能用进度条显示读到哪里了
file_dir = path + "/%02d" % i # 每个类别文件夹的路径名
file_list = os.listdir(file_dir) # 读每个类别的每张图片名,这里每个文件280张,os.listdir就是取每个图片成一个列表
xi = np.zeros((len(file_list), HW, HW, 3), dtype=np.uint8) # NumPy 函数,用于创建一个指定大小和形状的数组,并将所有元素初始化为 0,存取所有图片
yi = np.zeros((len(file_list)), dtype=np.uint8) # 数组,用于存每个图片的标签0-10
for j, each in enumerate(file_list): # 遍历当前类别的每张图片
img_path = file_dir + "/" + each # 每个类别的每张图片的完整路径
img = Image.open(img_path) # Image.open(img_path) 时,它会读取指定路径的图像文件,并将其转换为一个rgb图像对象
img = img.resize((HW, HW)) # 更改图片尺寸为224*224
xi[j, ...] = img # 将图片存入数组
yi[j] = i # 将图片的标签存入数组
# XY记录当前文件夹的数组,后面的每一轮都在此基础叠加。
# axis=0表示在第一个轴,即竖着拼接,比如第一轮的280张图片下面继续拼接第二轮的280张,即560张224*224*3的图片
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
# 数据集
class fooddataset(Dataset):
def __init__(self, path):
super(fooddataset, self).__init__()
self.X, self.Y = read_file(path)
self.Y = torch.LongTensor(self.Y)
self.transformer = train_transformer
def __getitem__(self, item):
return self.transformer(self.X[item]), self.Y[item] # 取一批数据时进行增广
def __len__(self):
return len(self.Y)
数据增广
我们给出具体尺寸的数据集,但是一旦图片缩小,或者翻转,计算机就不认识了,所以要将训练集的原始图片进行数据增广(随机旋转,放缩),让计算机提前见过各种图片。
当使用 DataLoader
来迭代数据集时,DataLoader
会在内部自动调用 __getitem__
方法来获取批次中的数据,数据增广就是在取一批训练集数据时进行的
# 训练集的数据增广。
train_transform = transforms.Compose([
transforms.ToPILImage(), # 转换PILImage格式
transforms.RandomResizedCrop(224), # 图片随机放大,再取其224的切片
transforms.RandomRotation(50), # 图片随机旋转
transforms.ToTensor() # 转为张量
])
模型
定义一个自己的模型(比较垃圾,最好迁移学习)
先用卷积层和池化层完成特征图尺寸的缩小:目标 3 * 224 * 224 -> 512 * 7 * 7
再拉直后为25088个参数,进入全连接层,最后得到11维向量
其中,前面的四个整体都可以封装成一个layer对象,一共4个layer,每一个包括一个卷积层Con