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

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

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

本文将介绍神经网络的一个这样的应用,并让读者了解如何使用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)
目录
相关文章
|
11天前
|
机器学习/深度学习 TensorFlow 算法框架/工具
利用Python和TensorFlow构建简单神经网络进行图像分类
利用Python和TensorFlow构建简单神经网络进行图像分类
34 3
|
13天前
|
机器学习/深度学习 人工智能 自动驾驶
深度学习的奇迹:如何用神经网络识别图像
【10月更文挑战第33天】在这篇文章中,我们将探索深度学习的奇妙世界,特别是卷积神经网络(CNN)在图像识别中的应用。我们将通过一个简单的代码示例,展示如何使用Python和Keras库构建一个能够识别手写数字的神经网络。这不仅是对深度学习概念的直观介绍,也是对技术实践的一次尝试。让我们一起踏上这段探索之旅,看看数据、模型和代码是如何交织在一起,创造出令人惊叹的结果。
24 0
|
1月前
|
机器学习/深度学习 PyTorch API
深度学习入门:卷积神经网络 | CNN概述,图像基础知识,卷积层,池化层(超详解!!!)
深度学习入门:卷积神经网络 | CNN概述,图像基础知识,卷积层,池化层(超详解!!!)
|
2月前
|
机器学习/深度学习 自然语言处理 计算机视觉
用于图像和用于自然语言的神经网络区别
主要区别总结 数据结构:图像数据是二维像素矩阵,具有空间结构;文本数据是一维序列,具有时间结构。 网络架构:图像处理常用CNN,注重局部特征提取;自然语言处理常用RNN/LSTM/Transformer,注重序列和全局依赖。 操作单元:图像处理中的卷积核在空间上操作;自然语言处理中的注意力机制在序列上操作。
24 2
|
3月前
|
机器学习/深度学习 人工智能 编解码
【神经网络】基于对抗神经网络的图像生成是如何实现的?
对抗神经网络,尤其是生成对抗网络(GAN),在图像生成领域扮演着重要角色。它们通过一个有趣的概念——对抗训练——来实现图像的生成。以下将深入探讨GAN是如何实现基于对抗神经网络的图像生成的
37 3
|
6月前
|
机器学习/深度学习 监控 自动驾驶
【传知代码】从零开始搭建图像去雾神经网络-论文复现
本文介绍了基于集成学习的双分支非均匀去雾神经网络的复现,该网络由迁移学习子网和数据拟合子网组成,分别处理全局表示和数据拟合。网络使用Res2Net作为编码器,并结合通道和像素注意力模块。代码可在提供的链接下载。网络在交通监控、自动驾驶、航海和目标跟踪等领域有广泛应用,通过提升图像质量来提高系统性能。实验在O-Haze、I-Haze和NH-Haze数据集上进行,展示了网络在去除雾霾方面的效果,尽管存在细节模糊和色彩饱和度低的问题。
156 1
|
6月前
|
机器学习/深度学习 PyTorch 算法框架/工具
Python用GAN生成对抗性神经网络判别模型拟合多维数组、分类识别手写数字图像可视化
Python用GAN生成对抗性神经网络判别模型拟合多维数组、分类识别手写数字图像可视化
|
5月前
|
机器学习/深度学习 PyTorch 算法框架/工具
【从零开始学习深度学习】26.卷积神经网络之AlexNet模型介绍及其Pytorch实现【含完整代码】
【从零开始学习深度学习】26.卷积神经网络之AlexNet模型介绍及其Pytorch实现【含完整代码】
|
5月前
|
机器学习/深度学习 PyTorch 算法框架/工具
【从零开始学习深度学习】28.卷积神经网络之NiN模型介绍及其Pytorch实现【含完整代码】
【从零开始学习深度学习】28.卷积神经网络之NiN模型介绍及其Pytorch实现【含完整代码】
|
3月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch代码实现神经网络
这段代码示例展示了如何在PyTorch中构建一个基础的卷积神经网络(CNN)。该网络包括两个卷积层,分别用于提取图像特征,每个卷积层后跟一个池化层以降低空间维度;之后是三个全连接层,用于分类输出。此结构适用于图像识别任务,并可根据具体应用调整参数与层数。