Trang này được dịch bởi Cloud Translation API.
Switch to English

Tải hình ảnh

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ tay

Hướng dẫn này chỉ ra cách tải và xử lý trước một tập dữ liệu hình ảnh theo ba cách. Đầu tiên, bạn sẽ sử dụng các tiện íchlớp tiền xử lý Keras cấp cao để đọc một thư mục hình ảnh trên đĩa. Tiếp theo, bạn sẽ viết đường dẫn đầu vào của riêng mình từ đầu bằng tf.data . Cuối cùng, bạn sẽ tải xuống một tập dữ liệu từ danh mục lớn có sẵn trong TensorFlow Datasets .

Thiết lập

import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
import tensorflow_datasets as tfds
print(tf.__version__)
2.3.0

Tải xuống bộ dữ liệu về hoa

Hướng dẫn này sử dụng một tập dữ liệu gồm hàng nghìn bức ảnh về hoa. Tập dữ liệu về hoa chứa 5 thư mục con, mỗi thư mục một lớp:

flowers_photos/
  daisy/
  dandelion/
  roses/
  sunflowers/
  tulips/
import pathlib
dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file(origin=dataset_url, 
                                   fname='flower_photos', 
                                   untar=True)
data_dir = pathlib.Path(data_dir)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
228818944/228813984 [==============================] - 1s 0us/step

Sau khi tải xuống (218MB), bây giờ bạn sẽ có sẵn một bản sao của các bức ảnh hoa. Có tổng số 3670 hình ảnh:

image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)
3670

Mỗi thư mục chứa hình ảnh của loại hoa đó. Đây là một số loại hoa hồng:

roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[0]))

png

roses = list(data_dir.glob('roses/*'))
PIL.Image.open(str(roses[1]))

png

Tải bằng keras.preprocessing

Hãy tải những hình ảnh này ra đĩa bằng image_dataset_from_directory .

Tạo tập dữ liệu

Xác định một số tham số cho bộ tải:

batch_size = 32
img_height = 180
img_width = 180

Bạn nên sử dụng phân tách xác thực khi phát triển mô hình của mình. Chúng tôi sẽ sử dụng 80% hình ảnh để đào tạo và 20% để xác thực.

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
Found 3670 files belonging to 5 classes.
Using 2936 files for training.

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
Found 3670 files belonging to 5 classes.
Using 734 files for validation.

Bạn có thể tìm thấy tên lớp trong thuộc tính class_names trên các tập dữ liệu này.

class_names = train_ds.class_names
print(class_names)
['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']

Trực quan hóa dữ liệu

Dưới đây là 9 hình ảnh đầu tiên từ tập dữ liệu đào tạo.

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 10))
for images, labels in train_ds.take(1):
  for i in range(9):
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(images[i].numpy().astype("uint8"))
    plt.title(class_names[labels[i]])
    plt.axis("off")

png

Bạn có thể đào tạo một mô hình bằng cách sử dụng các tập dữ liệu này bằng cách chuyển chúng đến model.fit (được hiển thị sau trong hướng dẫn này). Nếu muốn, bạn cũng có thể lặp lại theo cách thủ công qua tập dữ liệu và truy xuất hàng loạt hình ảnh:

for image_batch, labels_batch in train_ds:
  print(image_batch.shape)
  print(labels_batch.shape)
  break
(32, 180, 180, 3)
(32,)

image_batch là một tensor của hình dạng (32, 180, 180, 3) . Đây là một loạt 32 hình ảnh có hình dạng 180x180x3 (kích thước cuối cùng tham chiếu đến các kênh màu RGB). label_batch là một tenxơ của hình (32,) , đây là những nhãn tương ứng với 32 hình ảnh.

Chuẩn hóa dữ liệu

Các giá trị kênh RGB nằm trong phạm vi [0, 255] . Điều này không lý tưởng cho mạng nơ-ron; nói chung, bạn nên tìm cách giảm giá trị đầu vào của mình. Ở đây, chúng tôi sẽ chuẩn hóa các giá trị nằm trong [0, 1] bằng cách sử dụng lớp Thay đổi tỷ lệ.

from tensorflow.keras import layers

normalization_layer = tf.keras.layers.experimental.preprocessing.Rescaling(1./255)

Có hai cách để sử dụng lớp này. Bạn có thể áp dụng nó vào tập dữ liệu bằng cách gọi bản đồ:

normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
# Notice the pixels values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image)) 
0.0 0.96902645

Hoặc, bạn có thể bao gồm lớp bên trong định nghĩa mô hình của mình để đơn giản hóa việc triển khai. Chúng tôi sẽ sử dụng cách tiếp cận thứ hai ở đây.

Định cấu hình tập dữ liệu cho hiệu suất

Hãy đảm bảo sử dụng tìm nạp trước có bộ đệm để chúng ta có thể mang lại dữ liệu từ đĩa mà không bị chặn I / O. Đây là hai phương pháp quan trọng bạn nên sử dụng khi tải dữ liệu.

.cache() giữ hình ảnh trong bộ nhớ sau khi chúng được tải ra khỏi đĩa trong kỷ nguyên đầu tiên. Điều này sẽ đảm bảo tập dữ liệu không trở thành nút cổ chai trong khi đào tạo mô hình của bạn. Nếu tập dữ liệu của bạn quá lớn để vừa với bộ nhớ, bạn cũng có thể sử dụng phương pháp này để tạo bộ đệm ẩn trên đĩa hiệu quả.

.prefetch() chồng chéo tiền xử lý dữ liệu và thực thi mô hình trong khi đào tạo.

Bạn đọc quan tâm có thể tìm hiểu thêm về cả hai phương pháp cũng như cách lưu dữ liệu vào đĩa đệm trong phần hướng dẫn về hiệu suất dữ liệu .

AUTOTUNE = tf.data.experimental.AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

Đào tạo người mẫu

Để hoàn thiện, chúng tôi sẽ trình bày cách huấn luyện một mô hình đơn giản bằng cách sử dụng các bộ dữ liệu mà chúng tôi vừa chuẩn bị. Mô hình này chưa được điều chỉnh theo bất kỳ cách nào - mục đích là cho bạn thấy cơ chế sử dụng các bộ dữ liệu bạn vừa tạo. Để tìm hiểu thêm về phân loại hình ảnh, hãy truy cập hướng dẫn này.

num_classes = 5

model = tf.keras.Sequential([
  layers.experimental.preprocessing.Rescaling(1./255),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, activation='relu'),
  layers.MaxPooling2D(),
  layers.Flatten(),
  layers.Dense(128, activation='relu'),
  layers.Dense(num_classes)
])
model.compile(
  optimizer='adam',
  loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
  metrics=['accuracy'])
model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 6s 67ms/step - loss: 1.3187 - accuracy: 0.4401 - val_loss: 1.1184 - val_accuracy: 0.5681
Epoch 2/3
92/92 [==============================] - 1s 10ms/step - loss: 1.0639 - accuracy: 0.5838 - val_loss: 1.0369 - val_accuracy: 0.5926
Epoch 3/3
92/92 [==============================] - 1s 10ms/step - loss: 0.9236 - accuracy: 0.6458 - val_loss: 0.9955 - val_accuracy: 0.5995

<tensorflow.python.keras.callbacks.History at 0x7f1f5d110ba8>

Bạn có thể nhận thấy độ chính xác xác thực thấp so với độ chính xác đào tạo, cho thấy mô hình của chúng tôi đang được trang bị quá mức. Bạn có thể tìm hiểu thêm về việc trang bị quá nhiều và cách giảm nó trong hướng dẫn này.

Sử dụng tf.data để kiểm soát tốt hơn

Các tiện ích keras.preprocessing ở trên là một cách thuận tiện để tạo tf.data.Dataset từ một thư mục hình ảnh. Để kiểm soát hạt tốt hơn, bạn có thể viết đường dẫn đầu vào của riêng mình bằng tf.data . Phần này chỉ ra cách thực hiện điều đó, bắt đầu với các đường dẫn tệp từ zip mà chúng tôi đã tải xuống trước đó.

list_ds = tf.data.Dataset.list_files(str(data_dir/'*/*'), shuffle=False)
list_ds = list_ds.shuffle(image_count, reshuffle_each_iteration=False)
for f in list_ds.take(5):
  print(f.numpy())
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/3530500952_9f94fb8b9c_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/16656015339_2ccb7cd18d.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/8480886751_71d88bfdc0_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/14021281124_89cc388eac_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/2632216904_274aa17433.jpg'

Cấu trúc cây của tệp có thể được sử dụng để biên dịch danh sách class_names .

class_names = np.array(sorted([item.name for item in data_dir.glob('*') if item.name != "LICENSE.txt"]))
print(class_names)
['daisy' 'dandelion' 'roses' 'sunflowers' 'tulips']

Chia tập dữ liệu thành huấn luyện và xác thực:

val_size = int(image_count * 0.2)
train_ds = list_ds.skip(val_size)
val_ds = list_ds.take(val_size)

Bạn có thể thấy độ dài của mỗi tập dữ liệu như sau:

print(tf.data.experimental.cardinality(train_ds).numpy())
print(tf.data.experimental.cardinality(val_ds).numpy())
2936
734

Viết một hàm ngắn để chuyển đổi đường dẫn tệp thành cặp (img, label) :

def get_label(file_path):
  # convert the path to a list of path components
  parts = tf.strings.split(file_path, os.path.sep)
  # The second to last is the class-directory
  one_hot = parts[-2] == class_names
  # Integer encode the label
  return tf.argmax(one_hot)
def decode_img(img):
  # convert the compressed string to a 3D uint8 tensor
  img = tf.image.decode_jpeg(img, channels=3)
  # resize the image to the desired size
  return tf.image.resize(img, [img_height, img_width])
def process_path(file_path):
  label = get_label(file_path)
  # load the raw data from the file as a string
  img = tf.io.read_file(file_path)
  img = decode_img(img)
  return img, label

Sử dụng Dataset.map để tạo tập dữ liệu image, label các cặp image, label :

# Set `num_parallel_calls` so multiple images are loaded/processed in parallel.
train_ds = train_ds.map(process_path, num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(process_path, num_parallel_calls=AUTOTUNE)
for image, label in train_ds.take(1):
  print("Image shape: ", image.numpy().shape)
  print("Label: ", label.numpy())
Image shape:  (180, 180, 3)
Label:  3

Định cấu hình tập dữ liệu cho hiệu suất

Để đào tạo một mô hình với tập dữ liệu này, bạn sẽ muốn có dữ liệu:

  • Được xáo trộn tốt.
  • Để được chia lô.
  • Hàng loạt để có sẵn càng sớm càng tốt.

Các tính năng này có thể được thêm vào bằng cách sử dụng API tf.data . Để biết thêm chi tiết, hãy xem hướng dẫn Hiệu suất Đường ống Đầu vào .

def configure_for_performance(ds):
  ds = ds.cache()
  ds = ds.shuffle(buffer_size=1000)
  ds = ds.batch(batch_size)
  ds = ds.prefetch(buffer_size=AUTOTUNE)
  return ds

train_ds = configure_for_performance(train_ds)
val_ds = configure_for_performance(val_ds)

Trực quan hóa dữ liệu

Bạn có thể hình dung tập dữ liệu này tương tự như tập dữ liệu bạn đã tạo trước đó.

image_batch, label_batch = next(iter(train_ds))

plt.figure(figsize=(10, 10))
for i in range(9):
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(image_batch[i].numpy().astype("uint8"))
  label = label_batch[i]
  plt.title(class_names[label])
  plt.axis("off")

png

Tiếp tục đào tạo mô hình

Bây giờ bạn đã tạo thủ công một tf.data.Dataset tương tự như một tf.data.Dataset được tạo bởi keras.preprocessing ở trên. Bạn có thể tiếp tục đào tạo mô hình với nó. Như trước đây, chúng tôi sẽ huấn luyện chỉ trong một vài kỷ nguyên để giữ cho thời gian chạy ngắn.

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
Epoch 1/3
92/92 [==============================] - 2s 19ms/step - loss: 0.7869 - accuracy: 0.7054 - val_loss: 0.7747 - val_accuracy: 0.7071
Epoch 2/3
92/92 [==============================] - 1s 11ms/step - loss: 0.5762 - accuracy: 0.7892 - val_loss: 0.8838 - val_accuracy: 0.6689
Epoch 3/3
92/92 [==============================] - 1s 11ms/step - loss: 0.4070 - accuracy: 0.8556 - val_loss: 0.9416 - val_accuracy: 0.6812

<tensorflow.python.keras.callbacks.History at 0x7f1fc09c2828>

Sử dụng tập dữ liệu TensorFlow

Cho đến nay, hướng dẫn này tập trung vào việc tải dữ liệu ra đĩa. Bạn cũng có thể tìm thấy một tập dữ liệu để sử dụng bằng cách khám phá danh mục lớn các tập dữ liệu dễ tải xuống tại TensorFlow Datasets . Như trước đây bạn đã tải tập dữ liệu Flowers ra đĩa, hãy xem cách nhập tập dữ liệu đó bằng TensorFlow Datasets.

Tải xuống bộ dữ liệu về hoa bằng Bộ dữ liệu TensorFlow.

(train_ds, val_ds, test_ds), metadata = tfds.load(
    'tf_flowers',
    split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'],
    with_info=True,
    as_supervised=True,
)
Downloading and preparing dataset tf_flowers/3.0.1 (download: 218.21 MiB, generated: 221.83 MiB, total: 440.05 MiB) to /home/kbuilder/tensorflow_datasets/tf_flowers/3.0.1...

Warning:absl:Dataset tf_flowers is hosted on GCS. It will automatically be downloaded to your
local data directory. If you'd instead prefer to read directly from our public
GCS bucket (recommended if you're running on GCP), you can instead pass
`try_gcs=True` to `tfds.load` or set `data_dir=gs://tfds-data/datasets`.


Dataset tf_flowers downloaded and prepared to /home/kbuilder/tensorflow_datasets/tf_flowers/3.0.1. Subsequent calls will reuse this data.

Bộ dữ liệu hoa có năm lớp.

num_classes = metadata.features['label'].num_classes
print(num_classes)
5

Lấy hình ảnh từ tập dữ liệu.

get_label_name = metadata.features['label'].int2str

image, label = next(iter(train_ds))
_ = plt.imshow(image)
_ = plt.title(get_label_name(label))

png

Như trước đây, hãy nhớ hàng loạt, xáo trộn và định cấu hình từng tập dữ liệu cho hiệu suất.

train_ds = configure_for_performance(train_ds)
val_ds = configure_for_performance(val_ds)
test_ds = configure_for_performance(test_ds)

Bạn có thể tìm thấy một ví dụ hoàn chỉnh về cách làm việc với tập dữ liệu hoa và Tập dữ liệu TensorFlow bằng cách truy cập hướng dẫn tăng dữ liệu .

Bước tiếp theo

Hướng dẫn này chỉ ra hai cách tải hình ảnh ra đĩa. Đầu tiên, bạn đã học cách tải và xử lý trước một tập dữ liệu hình ảnh bằng cách sử dụng các lớp và tiện ích tiền xử lý của Keras. Tiếp theo, bạn đã học cách viết một đường dẫn đầu vào từ đầu bằng tf.data. Cuối cùng, bạn đã học cách tải xuống tập dữ liệu từ TensorFlow Datasets. Bước tiếp theo, bạn có thể tìm hiểu cách thêm dữ liệu tăng cường bằng cách truy cập hướng dẫn này. Để tìm hiểu thêm về tf.data, bạn có thể truy cập hướng dẫn này.