Tensorflow实现图像数据增强(Data Augmentation)

2022-02-23

当我们处理与图像相关的任务时,比如物体检测、分类、语义分割等,我们经常需要对训练集中的图像进行数据增强(data )。 ),这将增加训练集中的样本数量,使神经网络模型的泛化能力更强。在进行图像数据增强时,我们一般通过对图像进行翻转、裁剪、灰度变化、对比度变化、颜色变化等来生成新的训练集,这就是计算机视觉中的数据增强。让我们看看如何使用图像增强处理猫和狗图像分类的具体问题。源码可以在%查看

.

首先我们导入各种包,这里就不多说了。其中一个包称为 glob。该包主要用于读取本地计算机上的图像数据。这是非常容易使用。方便,几行代码就可以读取图片数据,比打包读取图片方便多了,代码如下:

import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import numpy as np
import glob
import os

然后为了看图,我把我所有的猫狗图片数据都放在了train文件夹里。这个文件夹下有两个文件夹,分别是dog和cat。在调用glob库写入图片路径时,我们直接用“*”表示读取一个文件夹下的所有文件,代码如下:

#首先获取图片,glob这个库明显感觉更加好用
train_image_path=glob.glob('F://UNIVERSITY STUDY/AI/dataset/catdog/train/*/*.jpg')
#加上*号是为了将当前目录下的所有文件,再加上一个星号是为了提取当前目录下的所有jpg文件
train_image_label=[int(p.split("\")[1]=='cat') for p in train_image_path ]
#经过一个列表推倒式就可以得到所有label

之后的第二行代码

是一个列表推导式,我们观察图像数据集的名称,发现每个图像名称上都有猫或狗。这样,我们就可以直接对名字上的狗和猫进行拆分,然后对拆分后的第二个字符串进行索引。这个字符串只是表示图片是猫还是狗。使用上面显示的列表推导,如果图像是猫,则标签为 1,如果是狗,则标签为 0。让我们看看数据集中的名称是什么样的:

从观察可以看出,名字是用句号分隔的,图片是jpg格式。

我们现在已经获得了所有图像的路径和标签,现在我们来看看最激动人心的部分,图像的数据增强! ! !

我们为图像编写了一个特殊的预处理,包括一个用于图像数据增强的函数:e()。在这个函数中,我们对图像进行预处理,然后调用它。该函数的代码如下:

#现在我们的jpg文件进行解码,变成三维矩阵
def load_preprosess_image(path,label):
    #读取路径
    image=tf.io.read_file(path)
    #解码
    image=tf.image.decode_jpeg(image,channels=3)#彩色图像为3个channel
    #将图像改变为同样的大小,利用裁剪或者扭曲,这里应用了扭曲
    image=tf.image.resize(image,[360,360])
    #随机裁剪图像
    image=tf.image.random_crop(image,[256,256,3])
    #随机上下翻转图像
    image=tf.image.random_flip_left_right(image)
    #随机上下翻转
    image=tf.image.random_flip_up_down(image)
    #随机改变图像的亮度
    image=tf.image.random_brightness(image,0.5)
    #随机改变对比度

图片[1]-Tensorflow实现图像数据增强(Data Augmentation)-唐朝资源网

image=tf.image.random_contrast(image,0,1) #改变数据类型 image=tf.cast(image,tf.float32) #将图像进行归一化 image=image/255 #现在还需要对label进行处理,我们现在是列表[1,2,3], #需要变成[[1].[2].[3]] label=tf.reshape(label,[1]) return image,label

评论我相信写的很详细,先将数据集中的图片后缀为jpg格式的图片解码,将jpg格式转换为三维矩阵,然后对图片进行处理,再剪切成256*256,因为我后面要搭建的神经网络如果图片的大小是256*256,那么这个网络的精度表现会更好。当然你也可以自己设计自己的神经网络,或者使用VGG16等卷积神经网络对图片进行分类。这些网络对图片的大小有一定的要求,所以我们必须预先准备好我们得到的图片。处理,不是每个数据集中的图片大小已经是一样的大小,方便训练。然后我们创建一个容器进行数据加载,同时制作每批数据,代码如下:

#现在开始创建dataset
train_image_ds=tf.data.Dataset.from_tensor_slices((train_image_path,train_image_label))
AUTOTUNE=tf.data.experimental.AUTOTUNE#根据计算机性能进行运算速度的调整
train_image_ds=train_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE)
#后面的参数表示处理并行运算的CPU运行数量
#现在train_image_ds就读取进来了,现在进行乱序和batchsize的规定
BATCH_SIZE=32
train_count=len(train_image_path)
#现在设置batch和乱序

train_image_ds=train_image_ds.shuffle(train_count).batch(BATCH_SIZE)
train_image_ds=train_image_ds.prefetch(AUTOTUNE)#预处理一部分处理,准备读取
imags,labels=iter(train_image_ds).next()#放到生成器里,单独取出数据

现在构建神经网络:

#现在开始创建模型
model=keras.Sequential([
tf.keras.layers.Conv2D(64,(3,3),input_shape=(256,256,3),activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(128,(3,3),activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(512,(3,3),activation='relu'),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(256,activation='relu'),
tf.keras.layers.Dense(1)
])

开始自定义训练。如果我们使用keras风格的编程,我们可以直接pile、model.fit和训练模型。但是这里为了在训练时能够看到模型的变化,我们使用自定义训练,这也是.0版本的优势。既可以通过自定义训练,也可以使用更方便的 keras 方法进行训练,这种方法要简单得多。自定义训练代码如下:

loss=tf.keras.losses.BinaryCrossentropy()#用这个来计算交叉熵
#定义优化器
optimizer=tf.keras.optimizers.Adam()

图片[2]-Tensorflow实现图像数据增强(Data Augmentation)-唐朝资源网

epoch_loss_avg
=tf.keras.metrics.Mean('train_loss')#定义平均损失 train_accuracy=tf.keras.metrics.Accuracy() def train_step(model,image,labels): with tf.GradientTape() as t: pred=model(image) #计算损失,比较标签值和预测值的区别 loss_step=tf.keras.losses.BinaryCrossentropy(from_logits=True)(labels,pred) grads=t.gradient(loss_step,model.trainable_variables)#计算梯度 optimizer.apply_gradients(zip(grads,model.trainable_variables))#根据梯度进行优化 epoch_loss_avg(loss_step) train_accuracy(labels,tf.cast(pred>0,tf.int32)) train_loss_results=[] train_acc_resuls=[] num_epochs=30 for epoch in range(num_epochs): for imgs_,labels_ in train_image_ds: train_step(model,imgs_,labels_) print('.',end=' ')#每一个batch就打印一个点 print()#换行 #还可以把train——loss拿进来 train_loss_results.append(epoch_loss_avg.result()) train_acc_resuls.append(train_accuracy) print('Epoch :{}.loss: {:.3f},acc:{:.3f}'.format(epoch+1,epoch_loss_avg.result(),train_accuracy.result())) epoch_loss_avg.reset_states()#重置目前的loss,这样就可以只用到了目前的平均loss train_accuracy.reset_states()

我还没有完成训练,让我们给你看一下前两个 epoch 的输出吧!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
Epoch :1.loss: 0.695,acc:0.491
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
Epoch :2.loss: 0.693,acc:0.500

这是使用图像数据增强,希望你能学到一些东西。

分类:

技术要点:

相关文章:

© 版权声明
THE END
喜欢就支持一下吧
点赞11赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容