Я новичок в искусственном интеллекте и пытаюсь объединить сверточные нейронные сети и рекуррентные нейронные сети или встраивание.
Если в качестве входных данных у нас есть две данные, первая из которых является изображением, а другая - текстом, изображение соответствует изображению продукта, а текст соответствует его описанию, а выходными данными является проверка соответствия продукта описанию или нет.
Для этого я уже собрал набор данных, в котором у меня есть изображение и описание в формате JSON, у меня даже есть код Embedding и CNN, но я не знаю, как их объединить, чтобы решить эту проблему.
На изображении ниже вы можете увидеть модель, которую я пытаюсь разработать:
Для CNN я использую Resnet v2
def lr_schedule(epoch):
lr = 1e-3
if epoch > 180:
lr *= 0.5e-3
elif epoch > 160:
lr *= 1e-3
elif epoch > 120:
lr *= 1e-2
elif epoch > 80:
lr *= 1e-1
print('Learning rate: ', lr)
return lr
def resnet_layer(inputs,
num_filters=16,
kernel_size=3,
strides=1,
activation='relu',
batch_normalization=True,
conv_first=True):
conv = Conv2D(num_filters,
kernel_size=kernel_size,
strides=strides,
padding='same',
kernel_initializer='he_normal',
kernel_regularizer=l2(1e-4))
x = inputs
if conv_first:
x = conv(x)
if batch_normalization:
x = BatchNormalization()(x)
if activation is not None:
x = Activation(activation)(x)
else:
if batch_normalization:
x = BatchNormalization()(x)
if activation is not None:
x = Activation(activation)(x)
x = conv(x)
return x
def resnet_v2(input_shape, depth):
if (depth - 2) % 9 != 0:
raise ValueError('depth should be 9n+2 (eg 56 or 110 in [b])')
# Start model definition.
num_filters_in = 16
num_res_blocks = int((depth - 2) / 9)
inputs = Input(shape=input_shape)
# v2 performs Conv2D with BN-ReLU on input before splitting into 2 paths
x = resnet_layer(inputs=inputs,
num_filters=num_filters_in,
conv_first=True)
# Instantiate the stack of residual units
for stage in range(3):
for res_block in range(num_res_blocks):
activation = 'relu'
batch_normalization = True
strides = 1
if stage == 0:
num_filters_out = num_filters_in * 4
if res_block == 0: # first layer and first stage
activation = None
batch_normalization = False
else:
num_filters_out = num_filters_in * 2
if res_block == 0: # first layer but not first stage
strides = 2 # downsample
# bottleneck residual unit
y = resnet_layer(inputs=x,
num_filters=num_filters_in,
kernel_size=1,
strides=strides,
activation=activation,
batch_normalization=batch_normalization,
conv_first=False)
y = resnet_layer(inputs=y,
num_filters=num_filters_in,
conv_first=False)
y = resnet_layer(inputs=y,
num_filters=num_filters_out,
kernel_size=1,
conv_first=False)
if res_block == 0:
# linear projection residual shortcut connection to match
# changed dims
x = resnet_layer(inputs=x,
num_filters=num_filters_out,
kernel_size=1,
strides=strides,
activation=None,
batch_normalization=False)
x = keras.layers.add([x, y])
num_filters_in = num_filters_out
# Add classifier on top.
# v2 has BN-ReLU before Pooling
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = AveragePooling2D(pool_size=8)(x)
y = Flatten()(x)
# Instantiate model.
model = Model(inputs=inputs, outputs=y)
return model
depth = 3 * 9 + 2
batch_size = 8
epochs = 200
num_classes = 10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
input_shape = x_train.shape[1:]
x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255
#x_train_mean = np.mean(x_train, axis=0)
#x_train -= x_train_mean
#x_test -= x_train_mean
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
print('y_train shape:', y_train.shape)
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
save_dir = os.path.join(os.getcwd(), 'saved_models')
model_name = 'a101.h5'
if not os.path.isdir(save_dir):
os.makedirs(save_dir)
filepath = os.path.join(save_dir, model_name)
checkpoint = ModelCheckpoint(filepath=filepath, monitor='val_acc', verbose=1, save_best_only=True)
lr_scheduler = LearningRateScheduler(lr_schedule)
model_image = resnet_v2(input_shape=input_shape, depth=depth)
model.compile(loss='binary_crossentropy', optimizer=Adam(lr=0.001), metrics=['accuracy'])
model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test), shuffle=True,
callbacks=[checkpoint, lr_scheduler])
Для встраивания это мой код (он работает отлично):
class A101Dataset(Dataset):
def __init__(self, json_file, images_dir, transform=None):
self.fb_model = gensim.models.KeyedVectors.load_word2vec_format('./cc.tr.300.vec', encoding='utf-8')
self.data = []
with open(json_file, encoding='utf-8') as f:
raw = json.load(f)
for item in raw:
for img in item['images']:
img_path = f'./Dataset/a101/images/{img}'
self.data.append((img_path, item['product_name']))
self.transform = transform
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
img_path, product_name = self.data[idx]
words = product_name.split()
sent_vec = np.mean([self.fb_model[w] for w in words], axis=0)
print(sent_vec.shape)
# image = io.imread(img_path)
image = cv2.imread(img_path)
# image = Image.open(img_path)
sample = {'image': image, 'sent_vec': sent_vec}
if self.transform:
sample['image'] = self.transform(sample['image'])
return sample
dataset = A101Dataset(json_file='./Dataset/a101/a101.json', images_dir='./Dataset/a101/images/')
Если кто-нибудь может дать совет, как решить проблему, я был бы очень признателен.