因此,出于系統特定的原因,我必須使用Tensorflow 1.9 。我想用一個由影像組成的自定義資料集來訓練一個 cnn。檔案夾結構看起來很像這樣:
./
circles
- circle-0.jpg
- circle-1.jpg
- ...
hexagons
- hexagon-0.jpg
- hexagon-1.jpg
- ...
...
因此,我必須使用的示例使用 MNIST 并具有以下兩行特定的代碼:
mnist_dataset = tf.keras.datasets.mnist.load_data('mnist_data')
(x_train, y_train), (x_test, y_test) = mnist_dataset
在我的作業中,我也不得不使用這種資料格式(x_train, y_train), (x_test, y_test),這似乎很常見。據我目前所知,這些資料集的格式是:(image_data, label),并且類似于((60000, 28, 28), (60000,)),至少對于 MNIST 資料集。這里image_data應該是dtype uint8(根據這篇文章)。我發現,一個tf.data.Dataset()物件看起來像我需要的元組(image_data, label)。
到目前為止,一切都很好。但是從這些資訊中產生了一些我還無法弄清楚的問題,我想在哪里請求你的幫助:
(60000, 28, 28)意味著 60k 一個 28 x 28 的影像值陣列,對嗎?- 如果 1. 是正確的,我如何將我的影像(如我上面描述的目錄結構)變成這種格式?是否有一個函式可以產生一個我可以這樣使用的陣列?
- 我知道我需要某種生成器函式來獲取所有帶有標簽的影像,因為在Tensorflow 1.9中
tf.keras.utils.image_dataset_from_directory()似乎還不存在。 - 標簽的實際外觀如何?例如,對于我的目錄結構,我會有這樣的東西:
(一種)
| 檔案 | 標簽 |
|---|---|
| 圓-0.jpg | 圓圈 |
| circle-233.jpg | 圓圈 |
| 六邊形-1.jpg | 六邊形 |
| 三角形-12.jpg | 三角形 |
或 (B)
| 檔案 | 標簽 |
|---|---|
| 圓-0.jpg | 圈0 |
| circle-233.jpg | 圓233 |
| 六邊形-1.jpg | 六邊形-1 |
| 三角形-12.jpg | 三角形 12 |
,其中相應的影像已經轉換為“ (60000, 28, 28)”格式?似乎我需要自己創建所有函式,因為似乎沒有一個好的函式可以將像我這樣的目錄結構帶到可以被Tensorflow 1.9使用的資料集,或者有嗎?我知道tf.keras.preprocessing.image.ImageDataGeneratorandimage_dataset_from_directory以及flow_from_directory(),但是,它們似乎都沒有給我帶來我想要的資料集值元組格式。
我真的很感激任何幫助!
uj5u.com熱心網友回復:
您必須為此構建一個自定義資料生成器。如果您有兩個陣列,train_paths其中包含影像的路徑和影像train_labels的標簽,那么此函式 ( datagen) 將生成影像作為陣列,并將它們各自的標簽作為元組(image_array, label)。
我還添加了一種使用字典對標簽進行整數編碼的方法encode_label
例如,train_paths并且train_labels應該如下所示:
train_paths = np.array(['path/to/image1.jpg','path/to/image2.jpg','path/to/image3.jpg'])
train_labels = np.array(['circle','square','hexagon'])
其中路徑'path/to/image1.jpg'的影像具有'circle'標簽,路徑'path/to/image2.jpg'的影像具有'square'標簽。
此生成器函式將作為批處理回傳資料,您也可以撰寫自定義增強技術(在augment函式內部)
import tensorflow as tf
# Hyperparameters
HEIGHT = 224 # Image height
WIDTH = 224 # Image width
CHANNELs = 3 # Image channels
# This function will encode your labels
encode_label = {'hexagon':0, 'circle':1, 'square':2}
def augment(image):
# All your augmentation techniques are done here
return image
def encode_labels(labels):
encoded = []
for label in labels:
encoded.append(encode_label[label])
return encoded
def open_images(paths):
'''
Given a list of paths to images, this function loads
the images from the paths, then augments them, then returns it as a batch
'''
images = []
for path in paths:
image = tf.keras.preprocessing.image.load_img(path, target_size=(HEIGHT, WIDTH, CHANNELS))
image = np.array(image)
image = augment(image)
images.append(image)
return np.array(images)
# This is the data generator
def datagen(paths, labels, batch_size=32):
for x in range(0,len(paths), batch_size):
# Load batch of images
batch_paths = paths[x:x batch_size]
batch_images = open_images(batch_paths)
# Load batch of labels
batch_labels = labels[x:x batch_size]
batch_labels = encode_labels(batch_labels)
batch_labels = np.array(batch_labels, dtype='float').reshape(-1)
yield batch_images, batch_labels
如果您無法tf.keras.preprocessing.image.load_img在 tensorflow 版本中作業,請嘗試使用替代方法來加載影像并調整其大小。另一種方法是使用 matplotlib 加載影像,然后使用 skimage 調整其大小。所以open_images函式是這樣的:
import matplotlib
from skimage.transform import resize
def open_images(paths):
'''
Given a list of paths to images, this function loads
the images from the paths, then augments them, then returns it as a batch
'''
images = []
for path in paths:
image = matplotlib.image.imread(path)
image = np.array(image)
image = resize(image, (HEIGHT, WIDTH, CHANNELS))
image = augment(image)
images.append(image)
return np.array(images)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/434161.html
上一篇:驗證損失增加而不是減少是否正常
下一篇:如何用資料集擬合keras模型?
