Оптимизация модели с несколькими входами в Tensorflow

#python #tensorflow #conv-neural-network

#python #tensorflow #conv-нейронная сеть

Вопрос:

Я работаю с медицинскими данными и пытаюсь построить модель TF с 2 входами.
-Первый вход представляет собой массив numpy, содержащий данные о нескольких пациентах. Некоторые тесты регулярно выполняются для каждого пациента (например, проверка веса пациента). Они будут появляться несколько раз в моем массиве.
-Второй — это изображение легких пациента.

Предположим, у меня есть 2 пациента по имени Боб и Джин. Боб был протестирован 3 раза, а Жан был протестирован 2 раза. У меня будет 3 строки в массиве для Боба и 2 строки для Джин. Но для каждого пациента у меня есть только одно изображение. Итак, в моем DataGenerator мне придется использовать это изображение 3 раза для каждой строки.
Мой первый ввод будет выглядеть так:

 ['Name', 'Age', 'Weight']  
['Bob', 54, 80]  
['Bob', 55, 81]  
['Bob', 52, 79]  
['Jean', 40, 90]   
['Jean', 41, 88]  
  

И второй, подобный этому:

 Bob_img = 'Array representing the image of Bob lungs' 
Jean_img = 'Array representing the image of Jean lungs' 

[Picture_array]
[Bob_img]
[Bob_img]
[Bob_img]
[Jean_img]
[Jean_img]
  

Я хочу создать CNN для обработки изображения, а затем объединить выходные данные CNN с массивом numpy.
В моем втором вводе есть повторение изображений. Он использует много оперативной памяти и выполняет одно и то же вычисление в CNN несколько раз. Итак, я хотел бы знать, есть ли какой-либо способ ее оптимизировать?

Модель более сложная, чем в следующем коде, но у вас должна быть идея с ней.

 image_input = K.Input(shape=(512, 512, 60,), name="img_input")
x = tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu')(image_input)
x = tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu')(x)
x = tf.keras.layers.MaxPool2D(pool_size=(2,2),strides=(2,2))(x)
cnn_output = tf.keras.layers.Flatten()(x)
    
numpy_input = K.Input(shape=(10,), name="numpy_input")
x = tf.keras.layers.concatenate([cnn_output, numpy_input], axis=1)
x = tf.keras.layers.Dense(32, activation='relu')(x)
x = tf.keras.layers.Dense(1, activation='relu')(x)

    
output= tf.keras.layers.Dense(1)(x)
    
model = K.Model(inputs=[image_input, numpy_input], outputs=output)
  

Построение модели:

 tf.keras.utils.plot_model(model, show_shapes=True)
  

Ссылка на модель

Комментарии:

1. Что вы подразумеваете под «Во-вторых, повторение образа «Пациента» каждый раз, когда он появляется, потребляет память»? Было бы полезно, если бы вы могли подробнее рассказать о своей проблеме.

2. @ShubhamPanchal Я отредактировал сообщение. Скажите мне, понятно ли это.

3. Понятия «У каждого «пациента» может быть несколько строк» и «повторение изображения «Пациента» каждый раз, когда он появляется, потребляет память» неясны, можете ли вы дать более подробную информацию.

4. @TouYou Я обновил сообщение. Тесты регулярно проводятся для каждого пациента. Каждый тест будет отображаться как строка в моем массиве. Изображение уникально для каждого пациента. Для каждой строки пациента я использую это изображение. Повторение этого изображения использует слишком много оперативной памяти. И изображение вычисляется несколько раз по CNN.

5. image_input = K.Input(форма = (512, 512, 60,) вы имели в виду форму = (512, 512, 60) с 60 каналами?

Ответ №1:

Наконец-то найден ответ: можно реализовать обучение с нуля. Затем решение состоит в том, чтобы перенаправить CNN, затем дополнить прямой проход CNN табличным вводом и применить прямой проход второй части NN. Наконец, мне просто нужно применить обратное распространение. Я поместил ссылку на руководство по написанию обучения с нуля здесь. И мой код, если он может быть полезен:

 epochs = 1
for epoch in range(epochs):
    print("nStart of epoch %d" % (epoch,))
    j=0

    # Iterate over the batches of the dataset.
    for [X1, X2], Y in generator:

        # Open a GradientTape to record the operations run
        # during the forward pass, which enables auto-differentiation.
        with tf.GradientTape() as tape:
            # Forward pass for CNN
            out_imgs = CNN(X2)
            # Replicate the forward pass in the same order than the numpy array
            patients = X1.loc[:, 'Patient'].unique()
            X_imgs = np.empty([X1.shape[0], out_imgs.shape[1]])
            for i in range(len(patients)):
                X_imgs[np.where(X1['Patient']==patients[i])] = out_imgs.numpy()[i]
            # Concatenate the forward pass with the numpy array
            inp_mlp = [tf.keras.layers.concatenate([0.1*X_imgs, np.asarray(X1[temp_SELECTED_COLUMNS])], axis=1)]
            # Forward pass of the second part of the layer
            for layer in model.layers[-3:]:
                inp_mlp.append(layer(inp_mlp[-1]))
            # Calculate loss
            loss = model.compiled_loss(tf.constant(Y), inp_mlp[-1], regularization_losses=model.losses)