我正在尝试HAM10000挑战,我已经确定了一些事情,例如第一次构建功能模型、分类等。我还没有弄清楚如何使用图像数据和患者元数据来训练我的模型。在我进一步讨论之前,这里是我的模型结构,这样你就可以理解我在这里试图做什么:
https://i.stack.imgur.com/ppQkm.png
该模型所做的是,它拍摄一张图像,并将其通过几个卷积层和最大池化层,然后将其压平。该模型还获取患者元数据,包括年龄、性别、色素位置等。然后将这些值连接在一起,并通过三个密集层,得出具有7个类别(akiec、bcc、bkl、df、mel、nv、vasc(的模型输出。
这是型号的代码:
# Imports
from tensorflow.keras.optimizers import Adam
from keras.utils.vis_utils import plot_model
import tensorflow as tf
from PIL import Image
import pandas as pd
import numpy as np
import json
import os
# Prevents CUBLAS_STATUS_ALLOC_FAILED errors
config = tf.compat.v1.ConfigProto(gpu_options=tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0.50))
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)
tf.compat.v1.keras.backend.set_session(session)
# Temporarily adds Graphviz to PATH
os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz/bin/'
# Loads metadata dataset
metadata = pd.read_csv("data/HAM10000_metadata.csv")
# Removes Lesion ID column
metadata = metadata.drop(["lesion_id"], axis=1)
# Loads translation key into memory
translation = json.loads(open("data/translation.json").read())
# Translates all non-numerical values into float64 values
metadata = metadata.replace(translation["dx_type"])
metadata = metadata.replace(translation["localization"])
metadata = metadata.replace(translation["sex"])
# "Shaves" off some data to make the model generalize better and to optimize memory usage
metadata = metadata.drop(metadata.iloc[:9300].index)
# Separates Image IDs and Labels to different variables
image_id = metadata.pop("image_id")
label = metadata.pop("dx")
# Converts metadata
metadata = np.array(metadata)
# Initializes image features set
image = np.zeros((len(image_id), 450, 600, 3), dtype=np.uint8)
# Iterates through extracted image IDs list and places RGB values into image features set
for i in image_id:
image[int(np.where(image_id == i)[0])] = np.array(Image.open("data/HAM10000_images/{}.jpg".format(i)))
print("data/HAM10000_images/{}.jpg Loaded | {:.5}%".format(i, str(100 * float(np.where(image_id == i)[0] + 1) / len(image_id))))
# Data dtype Changing
image = image.astype(float)
label = label.astype(float)
# Categorizing Variable Initialization
new_label = np.zeros((len(image_id), 7))
# Categorizing Reformatting
a = 0
for i in label:
if i == "akiec":
new_label[a] = np.array([1, 0, 0, 0, 0, 0, 0])
if i == "bcc":
new_label[a] = np.array([0, 1, 0, 0, 0, 0, 0])
if i == "bkl":
new_label[a] = np.array([0, 0, 1, 0, 0, 0, 0])
if i == "df":
new_label[a] = np.array([0, 0, 0, 1, 0, 0, 0])
if i == "mel":
new_label[a] = np.array([0, 0, 0, 0, 1, 0, 0])
if i == "nv":
new_label[a] = np.array([0, 0, 0, 0, 0, 1, 0])
if i == "vasc":
new_label[a] = np.array([0, 0, 1, 0, 0, 0, 1])
a += 1
# Convolutional Branch
image_input = tf.keras.layers.Input(shape=(450, 600, 3))
conv2D_1 = tf.keras.layers.Conv2D(8, kernel_size=(8, 8), activation='relu')(image_input)
max_pool_1 = tf.keras.layers.MaxPool2D((2, 2))(conv2D_1)
conv2D_2 = tf.keras.layers.Conv2D(8, kernel_size=(8, 8), activation='relu')(max_pool_1)
max_pool_2 = tf.keras.layers.MaxPool2D((2, 2))(conv2D_2)
flatten = tf.keras.layers.Flatten()(max_pool_2)
# Metadata Branch
metadata_input = tf.keras.layers.Input(shape=(4,))
# Concatenated Branch
concat = tf.keras.layers.Concatenate()([flatten, metadata_input])
hidden_1 = tf.keras.layers.Dense(128, activation='relu')(concat)
hidden_2 = tf.keras.layers.Dense(96, activation='relu')(hidden_1)
hidden_3 = tf.keras.layers.Dense(64, activation='relu')(hidden_2)
# Model Creation
output = tf.keras.layers.Dense(7, activation='softmax')(hidden_3)
model = tf.keras.Model(inputs=[image_input, metadata_input], outputs=[output])
# Prints structure of model
plot_model(model, to_file='model_plot.png', show_shapes=True, show_layer_names=True)
# Model Compilation
model.compile(optimizer=Adam(learning_rate=0.0001), loss="categorical_crossentropy")
# Model Training
model.fit(x=[image, metadata], y=new_label, batch_size=32, epochs=100000, validation_split=0.2)
我可以用fit((成功地传入元数据,但传入图像数据是最困难的部分。当我试图用float64的数据类型将大约9000个图像的RGB矩阵(600x450分辨率(加载到系统内存时,我的电脑显然崩溃了。然而,我能够成功地使用这项技术,将少量的图像加载到内存中(大约100张(,但这还不足以制作准确的模型。我尝试过ImageDataProcessing,但问题是fit_genearator((似乎不能接受我的元数据数据。
一个人告诉我;创建一个管道,根据模型的需要一次(或分批(加载一个图像;问题是,我找不到太多有用的文档可以做到这一点。
如果你能解决这个难题,我会洗耳恭听的。
谢谢!
虽然注释中的答案可能有效,但每当您试图传递这么多数据时,都应该使用DataGenerator。这是优化训练的最佳方式。
从那里你有两种可能性,要么你可以使用tf2(keras(提供的ImageDataGenerator
在您的情况下,它似乎不起作用,如果数据不简单,那也没关系,那么您应该创建自己的生成器:链接
您的自定义数据生成器将显示如下:
class DataGenerator(tf.keras.utils.Sequence):
def __init__(self, ...):
self.images = ...
self.metadata = ...
self.targets = ...
self.batch_size = ...
def __len__(self):
return int(np.floor(len(self.images) / self.batch_size))
def __getitem__(self, index):
return [self.images[index*self.batch_size:(index+1)*self.batch_size], self.metadata[self.images[index*self.batch_size:(index+1)*self.batch_size]], self.targets[index*self.batch_size:(index+1)*self.batch_size]
它会产生一批数据,不会溢出,而且你可以随心所欲。
顺便说一句,我认为fit_generator
已经被弃用了,你应该使用fit
。