我正在尝试训练网络的某些层,这些层的输入是图像和标量。请参阅下图以更好地了解。 。
如您所见,只会训练深黄色的层。因此,我需要冻结其余部分,以供稍后使用。
此体系结构的目的是将图像(胸部X射线)映射到14种疾病。
图像存储在以下目录中: / home / akde / chexnet / CheXNet-Keras / data / images
图像名称是图像ID。
数据帧将图像(图像称为图像ID)映射到类(疾病) 如您所见,图像可以映射到多个类别(疾病)。
另一个数据框将图像(图像ID)映射到患者年龄。您可以在下面看到它。
图像是第一输入,患者年龄是第二输入。
简而言之,对于每个图像ID,我都有一个图像和age值,它们分别位于2个单独的数据框中。
我已经可以使用以下代码进行测试(由于网络没有经过训练,因此得出了荒谬的结果,但仍然证明网络接受了输入并给出了一些结果)。
res3 = model3.predict( [test_image, a] )
其中a是标量输入,而test_image是图像输入。
我的训练数据存储在多个数据框中,在阅读了that帖子后,我推断应该使用 flow_from_dataframe 。
我做的第一件事是看this帖子,它解释了如何使用混合输入。这给了我一些背景知识,但是由于它不使用fit_generator(而是使用fit),因此无法解决我的问题。
然后,我读了this帖子,该帖子不使用多个输入。再次没有线索。
然后,我看到了this post,它以2张图像作为输入(而不是1张图像和一个标量)。再次没有帮助。
尽管我还没有找到解决问题的方法,但是我还是写了下面的代码来解决问题。
datagen=ImageDataGenerator(rescale=1./255., validation_split=0.25)
train_generator = datagen.flow_from_dataframe(traindf,
directory="/home/akde/chexnet/CheXNet-Keras/data/images",
class_mode="other",
x_col="Image Index",
y_col=["Atelectasis", "Cardiomegaly", "Effusion", "Infiltration", "Mass",
"Nodule", "Pneumonia", "Pneumothorax", "Consolidation", "Edema",
"Emphysema", "Fibrosis", "Pleural_Thickening", "Hernia"],
color_mode="rgb",
batch_size=32,
target_size=(224, 224)
)
STEP_SIZE_TRAIN=train_generator.n//train_generator.batch_size
model3.compile(optimizers.rmsprop(lr=0.0001, decay=1e-6),loss="categorical_crossentropy",metrics=["accuracy"])
model3.fit_generator(generator=train_generator,
steps_per_epoch=STEP_SIZE_TRAIN,
epochs=10
)
我知道这段代码离解决方案还很远。
那么我该如何创建一个使用2个数据帧的生成器,这两个数据帧已在前面进行了解释(一个将图像映射到疾病,另一个将图像ID映射到年龄)。
换句话说,考虑到图像和标量值均在数据帧中表示的事实,编写以图像和标量值作为输入的生成器的方式是什么。如何编写下面以粗体显示的生成器。model3.fit_generator(**generator=train_generator**,
steps_per_epoch=STEP_SIZE_TRAIN,
epochs=10
)
答案 0 :(得分:1)
出于您的目的,您需要创建一个自定义生成器。
我建议您深入了解此链接:
https://blog.ml6.eu/training-and-serving-ml-models-with-tf-keras-3d29b41e066c
尤其是这段代码:
import ast
import numpy as np
import math
import os
import random
from tensorflow.keras.preprocessing.image import img_to_array as img_to_array
from tensorflow.keras.preprocessing.image import load_img as load_img
def load_image(image_path, size):
# data augmentation logic such as random rotations can be added here
return img_to_array(load_img(image_path, target_size=(size, size))) / 255.
class KagglePlanetSequence(tf.keras.utils.Sequence):
"""
Custom Sequence object to train a model on out-of-memory datasets.
"""
def __init__(self, df_path, data_path, im_size, batch_size, mode='train'):
"""
df_path: path to a .csv file that contains columns with image names and labels
data_path: path that contains the training images
im_size: image size
mode: when in training mode, data will be shuffled between epochs
"""
self.df = pd.read_csv(df_path)
self.im_size = im_size
self.batch_size = batch_size
self.mode = mode
# Take labels and a list of image locations in memory
self.wlabels = self.df['weather_labels'].apply(lambda x: ast.literal_eval(x)).tolist()
self.glabels = self.df['ground_labels'].apply(lambda x: ast.literal_eval(x)).tolist()
self.image_list = self.df['image_name'].apply(lambda x: os.path.join(data_path, x + '.jpg')).tolist()
def __len__(self):
return int(math.ceil(len(self.df) / float(self.batch_size)))
def on_epoch_end(self):
# Shuffles indexes after each epoch
self.indexes = range(len(self.image_list))
if self.mode == 'train':
self.indexes = random.sample(self.indexes, k=len(self.indexes))
def get_batch_labels(self, idx):
# Fetch a batch of labels
return [self.wlabels[idx * self.batch_size: (idx + 1) * self.batch_size],
self.glabels[idx * self.batch_size: (idx + 1) * self.batch_size]]
def get_batch_features(self, idx):
# Fetch a batch of images
batch_images = self.image_list[idx * self.batch_size: (1 + idx) * self.batch_size]
return np.array([load_image(im, self.im_size) for im in batch_images])
def __getitem__(self, idx):
batch_x = self.get_batch_features(idx)
batch_y = self.get_batch_labels(idx)
return batch_x, batch_y
希望这将有助于找到您的解决方案!