我在 PyCharm 中使用 Tensorflow 和 keras 使用功能 api 创建了一个多输入网络。
如何将数据传递给这些模型的一个示例如下:
def create_model_multiple():
input1 = tf.keras.Input(shape=(13,), name = 'I1')
input2 = tf.keras.Input(shape=(6,), name = 'I2')
hidden1 = tf.keras.layers.Dense(units = 4, activation='relu')(input1)
hidden2 = tf.keras.layers.Dense(units = 4, activation='relu')(input2)
merge = tf.keras.layers.concatenate([hidden1, hidden2])
hidden3 = tf.keras.layers.Dense(units = 3, activation='relu')(merge)
output1 = tf.keras.layers.Dense(units = 2, activation='softmax', name ='O1')(hidden3)
output2 = tf.keras.layers.Dense(units = 2, activation='softmax', name = 'O2')(hidden3)
model = tf.keras.models.Model(inputs = [input1,input2], outputs = [output1,output2])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
x1 = np.random.uniform(0,1, (190,13))
x2 = np.random.uniform(0,1, (190,6))
val_x1 = np.random.uniform(0,1, (50,13))
val_x2 = np.random.uniform(0,1, (50,6))
y1 = np.random.randint(0,2, 190)
y2 = np.random.randint(0,2, 190)
val_y1 = np.random.randint(0,2, 50)
val_y2 = np.random.randint(0,2, 50)
model = create_model_multiple()
history = model.fit({'I1':x1, 'I2':x2},
{'O1':y1, 'O2': y2},
validation_data=([val_x1,val_x2], [val_y1,val_y2]), # <=========
epochs=100,
verbose = 1)
在上面的示例中,数据被加载为 NumPy 并形成为[val_x1,val_x2]
. 但是由于内存和数据集大小的限制,我必须使用 tf.data 来准备数据集。我的数据集由 2 个类中的图像组成(每个形状都是(5000,20)
。我加载了所有图像。网络输入层是1d-Cnn
每个接受的(5000,1)
。假设我给网络这样的输入:
X
是一个形状为(5000,20)的样本(图像),我必须将其转换为形状为(5000,1)的子样本x1,x2,......,x20,然后调用fit()
方法。
model.fit([x1,x2,x3,...,x20])
我的问题就在这里。我用tf.data
. 数据集的每个样本都有一个带有类的形状(5000,20)
和标签(2,1)
的图像样本。2
现在我无法将一个 tf 数据样本转换为给出model.fit()
方法的样本列表。
我用谷歌搜索并找到了这个解决方案,但它对我不起作用。
dataset = tf.data.Dataset(....) # suppose each sample in dataset is a triple (2-features and 1 label)
def input_solver(sample):
return {'input_1': sample[0], 'input_2': sample[1]}, sample[2]
dataset.map(input_solver) # this will map the first and the second feature in this triple-sample to the inputs.
model.fit(dataset, epochs=5)
这是我的完整代码:
import pathlib
import numpy as np
from tensorflow.keras.layers import Bidirectional,Conv1D,Input,MaxPooling1D,BatchNormalization,ReLU,concatenate,Flatten,LSTM,Dense
from tensorflow.keras.models import Model
import tensorflow as tf
import os
def conv_1d_block(num_block,visible1):
# visible1 = Input(shape=(n_steps, n_features))
cnn1_cnn = Conv1D(filters=32, kernel_size=1, activation='relu')(visible1)
cnn1_pool = MaxPooling1D(pool_size=25,padding='same')(cnn1_cnn)
cnn1_batchnorm = BatchNormalization()(cnn1_pool)
cnn1_relu = ReLU()(cnn1_batchnorm)
# cnn1_flat = Flatten()(cnn1_relu)
cnn2_cnn = Conv1D(filters=64, kernel_size=1, activation='relu')(cnn1_relu)
cnn2_pool = MaxPooling1D(pool_size=25,padding='same')(cnn2_cnn)
cnn2_batchnorm = BatchNormalization()(cnn2_pool)
cnn2_relu = ReLU()(cnn2_batchnorm)
cnn3_cnn = Conv1D(filters=128, kernel_size=1, activation='relu')(cnn2_relu)
cnn3_pool = MaxPooling1D(pool_size=12,padding='same')(cnn3_cnn)
cnn3_batchnorm = BatchNormalization()(cnn3_pool)
cnn3_relu = ReLU()(cnn3_batchnorm)
# cnn4_cnn = Conv1D(filters=256, kernel_size=1, activation='relu')(cnn3_relu)
# cnn4_pool = MaxPooling1D(pool_size=2)(cnn4_cnn)
# cnn4_batchnorm = BatchNormalization()(cnn4_pool)
# cnn4_relu = ReLU()(cnn4_batchnorm)
# cnn4_faltten = Flatten()(cnn4_relu)
# return cnn4_relu
return cnn3_relu
def build_model(num_signal):
input_all = []
cnn_all = []
# cnn_all_c = []
for j in range(num_signal):
input_temp = Input(shape=(n_steps, n_features))
cnn_temp = conv_1d_block(4,input_temp)
input_all.append(input_temp)
cnn_all.append(cnn_temp)
cnn_all_c = concatenate(cnn_all)
lstm_layer = Bidirectional(LSTM(256))(cnn_all_c)
fc1_layer = Dense(512,activation='relu')(lstm_layer)
fc2_layer = Dense(2,activation='softmax')(fc1_layer)
output_layer = fc2_layer
model = Model(inputs=input_all, outputs = output_layer)
return model
n_features = 1
n_steps = 5000
directory = "images_dir"
train_dir = pathlib.Path(directory)
CLASS_NAMES = np.array([item.name for item in train_dir.glob('*') if item.name != "LICENSE.txt"])
print(CLASS_NAMES)
full_dataset = tf.data.Dataset.list_files(str(train_dir/'*/*'))
validation_split = 0.2
DATASET_SIZE = len(list(full_dataset))
print("Dataset size: ", DATASET_SIZE)
train_size = int((1-validation_split) * DATASET_SIZE)
print("train size: ", train_size)
train_dataset = full_dataset.take(train_size)
validation_dataset = full_dataset.skip(train_size)
def get_label(file_path):
parts = tf.strings.split(file_path, os.path.sep)
return parts[-2] == CLASS_NAMES
def load_img(image_path):
img = tf.io.read_file(image_path)
img = tf.image.decode_image(img, 3, expand_animations=False)
img = tf.image.rgb_to_grayscale(img)
# img = tf.image.rot90(img)
img = tf.squeeze(img)
img = tf.cast(img, tf.float32)
return img
def normalize(image):
image = (image / 127.5) - 1
return image
def load_image_with_label(image_path):
label = get_label(image_path)
img = load_img(image_path)
return img, label
def load_image_train(image_file):
image, label = load_image_with_label(image_file)
image = normalize(image)
return image, label
def load_image_test(image_file):
image, label = load_image_with_label(image_file)
image = normalize(image)
# image = tf.squeeze(image)
return image, label
BATCH_SIZE = 5
SHUFFLE_BUFFER_SIZE = 1000
train_dataset1 = train_dataset.map(load_image_train)
train_dataset1 = train_dataset1.shuffle(SHUFFLE_BUFFER_SIZE)
# train_dataset = train_dataset.batch(BATCH_SIZE)
for image, label in train_dataset1.take(3):
print(image.shape)
print(label.shape)
print(label)
# validation_dataset = validation_dataset.map(load_image_test)
# validation_dataset = validation_dataset.batch(BATCH_SIZE)
def input_solver(sample,label):
keyf = "input_{}"
valf = "{}"
print("sample",sample[0])
print("sample shape",sample.shape)
# dictionary comprehension
# a = {keyf.format(i): valf.format(i) for i in range(1,n_ch+1)}
# can modify range to handle 1,000,000 if you wanted
# print(a)
return {'input_1': sample[0], 'input_2': sample[1],'input_3': sample[2],'input_4': sample[3],'input_5': sample[4],
'input_6': sample[5], 'input_7': sample[6],'input_8': sample[7],'input_9': sample[8],'input_10': sample[9],
'input_11': sample[10], 'input_12': sample[11],'input_13': sample[12],'input_14': sample[13],'input_15': sample[14],
'input_16': sample[15], 'input_17': sample[16],'input_18': sample[17],'input_19': sample[18],'input_20': sample[19]
}, label
# return {keyf.format(i): valf.format(sample[i]) for i in range(1,21)},label
# return {keyf.format(i): valf.format(sample[i]) for i in range(1,21)},label
# return {'input_1': sample[0], 'input_2': sample[1]}, sample[2]
# for image, label in validation_dataset.take(3):
# print(image.shape)
# print(label.shape)
# train_dataset2 = train_dataset1.map(input_solver)
for image, label in train_dataset1.take(3):
print(image.shape)
print(label.shape)
print(label)
train_dataset2 = train_dataset1.map(input_solver)
n_ch = 20
model = build_model(n_ch)
# model.summary()
model.compile(loss=tf.keras.losses.categorical_crossentropy,optimizer='adam',metrics=['accuracy'])
history = model.fit(train_dataset1,
epochs=100)
# history = model.fit(train_dataset,
# epochs=100,
# validation_data=validation_dataset)