ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Tensorflow学习笔记 (用 tf.data 加载图片)

2021-09-04 09:59:18  阅读:341  来源: 互联网

标签:image label path tf Tensorflow data ds


原代码来自tensorflow

Tensorflow学习笔记 (用 tf.data 加载图片)

在这里插入图片描述

本教程提供一个如何使用 tf.data 加载图片的简单例子。

导入模块,配置

import tensorflow as tf

tf.data用于数据集的构建与预处理

AUTOTUNE = tf.data.experimental.AUTOTUNE

下载并检查数据集

从origin网址中下载文件,命名为’flower_photos’,untar=True表示对文件进行解压。
通过pathlib.Path(data_root_orig)获得文件的路径(虽然data_root_orig 也表示下载的文件路径,但pathlib.Path可以支持不同的操作系统)

import pathlib
data_root_orig = tf.keras.utils.get_file(origin='https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',                                   fname='flower_photos', untar=True)
data_root = pathlib.Path(data_root_orig)
print(data_root)

查看data_root路径下的文件

data_root路径下有5个子文件夹和1txt文件。

for item in data_root.iterdir():
  print(item)

在这里插入图片描述data_root.路径下有6个子文件,data_root.glob(’/’)表示读取子文件夹中的所有图片。

import random
all_image_paths = list(data_root.glob('*/*'))
all_image_paths

列表中的部分内容如下所示
[WindowsPath(‘C:/Users/HUAWEI/.keras/datasets/flower_photos/daisy/100080576_f52e8ee070_n.jpg’),
WindowsPath(‘C:/Users/HUAWEI/.keras/datasets/flower_photos/daisy/10140303196_b88d3d6cec.jpg’),

去掉WindowsPath,只留下图片的路径

all_image_paths = [str(path) for path in all_image_paths]
all_image_paths

在这里插入图片描述
打乱图片路径顺序
查看一共有多少图片

random.shuffle(all_image_paths)

image_count = len(all_image_paths)
image_count

检查图片

打开data_root路径下的"LICENSE.txt"文件,编码为’utf-8’,读取文件第4行以后的内容。
将列表中的每一项以’ CC-BY’作为分隔符分开。

import os
attributions = (data_root /"LICENSE.txt").open(encoding='utf-8').readlines()[4:]
attributions = [line.split(' CC-BY') for line in attributions]

将attributions变成字典

attributions = dict(attributions)
attributions

在这里插入图片描述

caption_image是一个查看图片拍摄者的函数。将图片在计算机中的路径作为参数输入,用pathlib.Path将路径变成本机系统适用的路径。image_path相当于data_root的一个子集,pathlib.Path(image_path).relative_to(data_root)相当于将image_path减去data_root。示例如下

import IPython.display as display

def caption_image(image_path):
    image_rel = pathlib.Path(image_path).relative_to(data_root)
    return "Image (CC BY 2.0) " + ' - '.join(attributions[str(image_rel)].split(' - ')[:-1])

随机选取3张图片,浏览图片并打印其拍摄者

for n in range(3):
  image_path = random.choice(all_image_paths)
  display.display(display.Image(image_path))
  print(caption_image(image_path))
   print()

确定可用的标签

查看data_root路径下的所有文件(5个文件夹,1个txt文件),如果文件是文件夹时,将文件的文件名选出并排序。

label_names = sorted(item.name for item in data_root.glob('*/') if item.is_dir())
label_names

通过枚举的方法,为每个标签分配索引。

label_to_index = dict((name, index) for index, name in enumerate(label_names))
label_to_index

设置所有图片的标签。通过for path in all_image_paths得到所有图片的路径,形如’/home/kbuilder/.keras/datasets/flower_photos/tulips/8673416166_620fc18e2f_n.jpg’,pathlib.Path(path).parent.name可以得到图片上一级文件夹的名称,如tulips。
通过键值对匹配给所有图片贴上标签。

all_image_labels = [label_to_index[pathlib.Path(path).parent.name]
                    for path in all_image_paths]

print("First 10 labels indices: ", all_image_labels[:10])

加载并格式化图片

加载并格式化图片,使图片适用于模型训练。
通过tf.io.read_file()和图片路径读取原始数据,返回给image,将原始数据image解码为图像tensor.

def load_and_preprocess_image(path):
  image = tf.io.read_file(path)
  return preprocess_image(image)

该函数用于原始数据的解码,image是原始数据。tf.image.decode_jpeg用于对图片的解码,channels=3表示输出RGB图像,最后返回uint8类型的Tensor。
对图像大小进行调整,[192, 192]表示新图像的大小。
对图像进行归一化处理。

def preprocess_image(image):
  image = tf.image.decode_jpeg(image, channels=3)
  image = tf.image.resize(image, [192, 192])
  image /= 255.0  # normalize to [0,1] range

  return image

查看调整后的图像
不显示网格线
设置横坐标
设置标题,并将首字母大写

import matplotlib.pyplot as plt

image_path = all_image_paths[0]
label = all_image_labels[0]

plt.imshow(load_and_preprocess_image(img_path))
plt.grid(False)
plt.xlabel(caption_image(img_path))
plt.title(label_names[label].title())
print()

构建一个 tf.data.Dataset

构建 tf.data.Dataset 最简单的方法就是使用 from_tensor_slices 方法。
将字符串数组切片,得到一个字符串数据集:

path_ds = tf.data.Dataset.from_tensor_slices(all_image_paths)

现在创建一个新的数据集,通过在路径数据集上映射 preprocess_image 来动态加载和格式化图片,返回一个迭代器。即通过load_and_preprocess_image将path_ds映射至image_ds,动态加载和格式化图片。

image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE)

浏览图片

import matplotlib.pyplot as plt

plt.figure(figsize=(8,8))
for n, image in enumerate(image_ds.take(4)):
  plt.subplot(2,2,n+1)
  plt.imshow(image)
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])
  plt.xlabel(caption_image(all_image_paths[n]))
  plt.show()

使用同样的 from_tensor_slices 方法你可以创建一个标签数据集

label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(all_image_labels, tf.int64))

由于这些数据集顺序相同,你可以将他们打包在一起得到一个(图片, 标签)对数据集:

image_label_ds = tf.data.Dataset.zip((image_ds, label_ds))


ds = tf.data.Dataset.from_tensor_slices((all_image_paths, all_image_labels))

元组被解压缩到映射函数的位置参数中

def load_and_preprocess_from_path_label(path, label):
  return load_and_preprocess_image(path), label

image_label_ds = ds.map(load_and_preprocess_from_path_label)
image_label_ds

训练时,数据应充分打乱,分割为batch,永远穿越重复,尽可能提供batch

BATCH_SIZE = 32

设置一个和数据集大小一致的 shuffle buffer size(随机缓冲区大小)以保证数据被充分打乱。

ds = image_label_ds.shuffle(buffer_size=image_count)
ds = ds.repeat()
ds = ds.batch(BATCH_SIZE)

当模型在训练的时候,prefetch 使数据集在后台取得 batch。

ds = ds.prefetch(buffer_size=AUTOTUNE)
ds
ds = image_label_ds.apply(
  tf.data.experimental.shuffle_and_repeat(buffer_size=image_count))
ds = ds.batch(BATCH_SIZE)
ds = ds.prefetch(buffer_size=AUTOTUNE)
ds

传递数据至模型

mobile_net = tf.keras.applications.MobileNetV2(input_shape=(192, 192, 3), include_top=False)
mobile_net.trainable=False

该模型期望它的输出被标准化至 [-1,1] 范围内,在你将输出传递给 MobilNet 模型之前,你需要将其范围从 [0,1] 转化为 [-1,1]:

def change_range(image,label):
  return 2*image-1, label

keras_ds = ds.map(change_range)

构建一个包装了 MobileNet 的模型并在 tf.keras.layers.Dense 输出层之前使用 tf.keras.layers.GlobalAveragePooling2D 来平均那些空间向量:

model = tf.keras.Sequential([
  mobile_net,
  tf.keras.layers.GlobalAveragePooling2D(),
  tf.keras.layers.Dense(len(label_names), activation = 'softmax')])
logit_batch = model(image_batch).numpy()

print("min logit:", logit_batch.min())
print("max logit:", logit_batch.max())
print()

print("Shape:", logit_batch.shape)

编译模型

model.compile(optimizer=tf.keras.optimizers.Adam(),
              loss='sparse_categorical_crossentropy',
              metrics=["accuracy"])

查看Dense层可训练的变量个数

len(model.trainable_variables)

model.summary()

注意,出于演示目的每一个 epoch 中你将只运行 3 step,但一般来说在传递给 model.fit() 之前你会指定 step 的真实数量

steps_per_epoch=tf.math.ceil(len(all_image_paths)/BATCH_SIZE).numpy()
steps_per_epoch

model.fit(ds, epochs=1, steps_per_epoch=3)

标签:image,label,path,tf,Tensorflow,data,ds
来源: https://blog.csdn.net/DNDAW/article/details/120094666

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有