使用神经网络为图像生成标题(上)

本文涉及的产品
NLP自然语言处理_基础版,每接口每天50万次
NLP 自学习平台,3个模型定制额度 1个月
NLP自然语言处理_高级版,每接口累计50万次
简介: 使用神经网络为图像生成标题

我们都知道,神经网络可以在执行某些任务时复制人脑的功能。神经网络在计算机视觉和自然语言生成方面的应用已经非常引人注目。

本文将介绍神经网络的一个这样的应用,并让读者了解如何使用CNNs和RNNs (LSTM)的混合网络实际为图像生成标题(描述)。我们在这个任务中使用的数据集是流行的flickr 8k图像数据集,它是这个任务的基准数据,可以通过下面的链接访问。

Kaggle — https://www.kaggle.com/adityajn105/flickr8k

注意:我们将把数据集分割为7k用于训练,1k用于测试。

我们将首先讨论在我们的混合神经网络中不同的组件(层)和它们的功能。与此同时,我们还将研究使用Tensorflow、Keras和Python开发混合神经网络的实际实现。

神经网络的总体结构

让我们来看看我们将用于生成字幕的神经网络的总体架构。

640.png

简单地说,上述神经网络有3个主要组成部分(子网络),每个子网络都有一个特定的任务,即卷积网络(用于从图像中提取特征)、rstm(用于生成文本)和解码器(用于合并两种网络)。

现在让我们详细讨论每个组件并了解它们的工作原理。

图像特征提取器

为了从图像中生成特征,我们将使用卷积神经网络,只需稍加修改。让我们来看看一个用于图像识别的卷积神经网络。

640.jpg

一般的CNN分类模型有两个子网络

Feature Learning Network—负责从图像中生成Feature map的网络(多卷积和池化层的网络)。

分类网络——负责图像分类的全连通深度神经网络(多稠密层、单输出层网络)。

由于我们只对从图像中提取特征感兴趣,而对其分类不感兴趣,所以我们只对CNN的Feature Learning部分进行处理,这就是我们从图像中提取特征的方法。

下面的代码可以用来从任何一组图像提取特征:

import tensorflow as tf
from keras.preprocessing import image
import numpy as np
# function to extract features from image
def extract_image_features():
    model = tf.keras.models.Sequential()
    # adding first layers of convolution and pooling layers to network
    model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=(3,3), input_shape=(90,90,3), padding="VALID", activation="relu"))
    model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=(3,3), activation="relu"))
    model.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2))
    # adding second layers of convolution and pooling layers to network
    model.add(tf.keras.layers.Conv2D(filters=32, kernel_size=(3,3), padding="VALID", activation="relu"))
    model.add(tf.keras.layers.Conv2D(filters=32, kernel_size=(3,3), activation="relu"))
    model.add(tf.keras.layers.AveragePooling2D(pool_size=2, strides=1))
    # flattening the output using flatten layer, since the input to neural net has to be flat
    model.add(tf.keras.layers.Flatten())
    # model summary
    model.summary()
    return model
for file in os.listdir(image_path):
    path = image_path + "//" + file
    img = image.load_img(path, target_size=(90, 90))
    img_data = image.img_to_array(img)
    img_data = np.expand_dims(img_data, axis=0)
    img_data = preprocess_input(img_data)
    feature = extract_image_features.predict(img_data)
    feature = np.reshape(feature, feature.shape[1])

任何人都可以使用上述代码构建自己的图像特征提取器,但有一个问题…

上面的模型太过简单,无法从我们的一组图像中提取出每一个重要的细节,因此会影响整个模型的性能。此外,由于高性能gpu和系统的不可用性,使得模型过于复杂(具有大量神经元的多层密集层)也具有挑战性。

为了解决这个问题,我们在Tensorflow中有非常流行的预训练CNN模型(VGG-16, ResNet50等,由不同大学和组织的科学家开发),可以用于从图像中提取特征。记住,在使用输出层进行特征提取之前,要将它从模型中移除。

下面的代码将让您了解如何使用Tensorflow中这些预先训练好的模型从图像中提取特征。

import tensorflow as tf
from keras.preprocessing import image
from keras.applications.resnet50 import ResNet50
from keras.applications.resnet50 import preprocess_input
from keras.models import Model
# load the ResNet50 Model
feature_extractor = ResNet50(weights='imagenet', include_top=False)
feature_extractor_new = Model(feature_extractor.input, feature_extractor.layers[-2].output)
feature_extractor_new.summary()
for file in os.listdir(image_path):
    path = image_path + "//" + file
    img = image.load_img(path, target_size=(90, 90))
    img_data = image.img_to_array(img)
    img_data = np.expand_dims(img_data, axis=0)
    img_data = preprocess_input(img_data)
    feature = feature_extractor_new.predict(img_data)
    feature_reshaped = np.array(feature).flatten()

正如您在下面看到的,如果执行上面的代码,您将看到我们的图像特性只是一个形状-(18432,)的numpy数组。

image_feature_dictionary[list(image_feature_dictionary. Keys())[0]].shape
(18432,)

接下来,我们将开发用于为图像生成标题的LSTM网络(RNN)。

用于生成标题的LSTM

文本生成是LSTM网络中最流行的应用之一。LSTM单元格(LSTM网络的基本构建块)能够根据前一层的输出生成输出,即它保留前一层(内存)的输出,并使用该内存生成(预测)序列中的下一个输出。

对于我们的数据集,我们为每张图片设置了5个标题,即总共40k个标题。

让我们看看我们的数据集-

640.jpg

  1. *A child in a pink dress is climbing up a set of stairs in an entry way.*
  2. *A girl going into a wooden building.*
  3. *A little girl climbing into a wooden playhouse.*
  4. *A little girl climbing the stairs to her playhouse.*
  5. *A little girl in a pink dress going into a wooden cabin.*

正如所见,所有的字幕都很好地描述了图片。我们现在的任务是设计一个RNN,它可以为任何相似的图像集复制这个任务。

回到最初的任务,我们首先必须看看LSTM网络是如何生成文本的。对于LSTM来说,网络标题只不过是一长串单独的单词(编码为数字)放在一起。利用这些信息,它试图根据前面的单词预测序列中的下一个单词(记忆)。

在我们的例子中,由于标题可以是可变长度的,所以我们首先需要指定每个标题的开始和结束。我们看看-是什么意思

640.jpg

首先,我们将把<start><end>添加到数据集中的每个标题中。在创建最终词汇表之前,我们将对训练数据集中的每个标题进行标记。为了训练我们的模型,我们将从词汇表中删除频率小于或等于10的单词。增加这一步是为了提高我们的模型的一般性能,并防止它过拟合训练数据集。

代码如下:

# loading captions from captions file
import pandas as pd
# loading captions.txt
captions = pd.read_csv('/kaggle/input/flickr8k/captions.txt', sep=",")
captions = captions.rename(columns=lambda x: x.strip().lower())
captions['image'] = captions['image'].apply(lambda x: x.split(".")[0])
captions = captions[['image', 'caption']]
# adding <start> and <end> to every caption
captions['caption'] = "<start> " + captions['caption'] + " <end>"
# in case we have any missing caption/blank caption drop it
print(captions.shape)
captions = captions.dropna()
print(captions.shape)
# training and testing image captions split
train_image_captions = {}
test_image_captions = {}
# list for storing every caption
all_captions = []
# storing training data
for image in train_data_images:
    tempDf = captions[captions['image'] == image]
    list_of_captions = tempDf['caption'].tolist()
    train_image_captions[image] = list_of_captions
    all_captions.append(list_of_captions)
# store testing data
for image in test_data_images:
    tempDf = captions[captions['image'] == image]
    list_of_captions = tempDf['caption'].tolist()
    test_image_captions[image] = list_of_captions
    all_captions.append(list_of_captions)
print("Data Statistics")
print(f"Training Images Captions {len(train_image_captions.keys())}")
print(f"Testing Images Captions {len(test_image_captions.keys())}")

上面的代码将生成下面的输出

train_image_captions[list(train_image_captions. Keys())[150]]
['<start> A brown dog chases a tattered ball around the yard . <end>',
  '<start> A brown dog is chasing a tattered soccer ball across a low cut field . <end>',
  '<start> Large brown dog playing with a white soccer ball in the grass . <end>',
  '<start> Tan dog chasing a ball . <end>',
  '<start> The tan dog is chasing a ball . <end>']

一旦我们加载了标题,我们将首先使用spacy和Tokenizer(来自tensorflow.preprocessing.)对所有内容进行标记。文本类)。

令牌化就是将一个句子分解成不同的单词,同时删除特殊字符,所有内容都小写。结果是我们在句子中有了一个有意义的单词(记号)的语料库,我们可以在将其用作模型的输入之前对其进行进一步编码。

import spacy
nlp = spacy.load('en', disable=['tagger', 'parser', 'ner'])
# tokenize evry captions, remove punctuations, lowercase everything
for key, value in train_image_captions.items():
    ls = []
    for v in value:
        doc = nlp(v)
        new_v = " "
        for token in doc:
            if not token.is_punct:
                if token.text not in [" ", "\n", "\n\n"]:
                    new_v = new_v + " " + token.text.lower()
        new_v = new_v.strip()
        ls.append(new_v)
    train_image_captions[key] = ls
# create a vocabulary of all the unique words present in captions
# flatten the list
all_captions = [caption for list_of_captions in all_captions for caption in list_of_captions]
# use spacy to convert to lowercase and reject any special characters
tokens = []
for captions in all_captions:
    doc = nlp(captions)
    for token in doc:
        if not token.is_punct:
            if token.text not in [" ", "\n", "\n\n"]:
                tokens.append(token.text.lower())
# get tokens with frequency less than 10
import collections
word_count_dict = collections.Counter(tokens)
reject_words = []
for key, value in word_count_dict.items():
    if value < 10:
        reject_words.append(key)
reject_words.append("<")
reject_words.append(">")
  # remove tokens that are in reject words
tokens = [x for x in tokens if x not in reject_words]
# convert the token to equivalent index using Tokenizer class of Keras
from keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer()
tokenizer.fit_on_texts(tokens)
目录
相关文章
|
1月前
|
机器学习/深度学习 算法 PyTorch
python手把手搭建图像多分类神经网络-代码教程(手动搭建残差网络、mobileNET)
python手把手搭建图像多分类神经网络-代码教程(手动搭建残差网络、mobileNET)
77 0
|
1月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
PYTHON TENSORFLOW 2二维卷积神经网络CNN对图像物体识别混淆矩阵评估|数据分享
PYTHON TENSORFLOW 2二维卷积神经网络CNN对图像物体识别混淆矩阵评估|数据分享
|
1月前
|
机器学习/深度学习 监控 自动驾驶
【传知代码】从零开始搭建图像去雾神经网络-论文复现
本文介绍了基于集成学习的双分支非均匀去雾神经网络的复现,该网络由迁移学习子网和数据拟合子网组成,分别处理全局表示和数据拟合。网络使用Res2Net作为编码器,并结合通道和像素注意力模块。代码可在提供的链接下载。网络在交通监控、自动驾驶、航海和目标跟踪等领域有广泛应用,通过提升图像质量来提高系统性能。实验在O-Haze、I-Haze和NH-Haze数据集上进行,展示了网络在去除雾霾方面的效果,尽管存在细节模糊和色彩饱和度低的问题。
|
1月前
|
机器学习/深度学习 数据可视化 数据挖掘
R语言深度学习卷积神经网络 (CNN)对 CIFAR 图像进行分类:训练与结果评估可视化
R语言深度学习卷积神经网络 (CNN)对 CIFAR 图像进行分类:训练与结果评估可视化
|
1月前
|
机器学习/深度学习 PyTorch 算法框架/工具
Python用GAN生成对抗性神经网络判别模型拟合多维数组、分类识别手写数字图像可视化
Python用GAN生成对抗性神经网络判别模型拟合多维数组、分类识别手写数字图像可视化
|
1月前
|
机器学习/深度学习 算法 TensorFlow
【视频】神经网络正则化方法防过拟合和R语言CNN分类手写数字图像数据MNIST|数据分享
【视频】神经网络正则化方法防过拟合和R语言CNN分类手写数字图像数据MNIST|数据分享
|
1月前
|
机器学习/深度学习 编解码 异构计算
ELAN:用于图像超分辨率的高效远程注意力网络
ELAN:用于图像超分辨率的高效远程注意力网络
72 1
|
1月前
|
前端开发 PyTorch 算法框架/工具
【基础实操】借用torch自带网络进行训练自己的图像数据
【基础实操】借用torch自带网络进行训练自己的图像数据
38 0
【基础实操】借用torch自带网络进行训练自己的图像数据
|
1月前
|
机器学习/深度学习 算法 Python
【Siamese】手把手教你搭建一个孪生神经网络,比较两张图像的相似度
【Siamese】手把手教你搭建一个孪生神经网络,比较两张图像的相似度
171 0
|
20天前
|
网络协议 算法 Linux
【嵌入式软件工程师面经】Linux网络编程Socket
【嵌入式软件工程师面经】Linux网络编程Socket
39 1

热门文章

最新文章