使用TensorFlow建立计算机视觉模型

366 阅读12分钟

DZone>AI专区>使用TensorFlow建立计算机视觉模型

使用TensorFlow建立计算机视觉模型

随着TensorFlow 2.0的发布和Keras库的集成作为高级API,构建和训练深度学习架构变得很容易。

Kevin Vu user avatar 通过

凯文-武

-

Sep. 15, 22 - AI Zone- 教程

喜欢 (1)

评论

保存

鸣谢

94 次浏览

加入DZone社区,获得完整的会员体验。

免费加入

什么是计算机视觉?

计算机视觉(CV)是现代人工智能(AI)和机器学习(ML)系统的一项主要任务。它正在加速行业中的几乎每个领域,使组织能够彻底改变机器和业务系统的工作方式。

在学术上,它是计算机科学的一个成熟领域,许多几十年的研究工作已经进入了这个领域,使其变得丰富。最近,深度神经网络的使用彻底改变了这一领域,并赋予其新的生命。

计算机视觉的应用领域多种多样,如:。

  • 自主驾驶
  • 医学成像分析和诊断
  • 制造缺陷的检测
  • 监控录像的图像和视频分析
  • 安全系统的面部识别

当然,还有很多与CV系统有关的挑战。例如,自动驾驶不只是使用物体检测,还包括物体分类、分割、运动检测等。

除此之外,这些系统还要在几分之一秒内处理CV信息,并产生一个高概率的决定。更高层次的监督控制系统必须做出决定,负责最终的驾驶任务。

此外,在任何值得尊敬的自动驾驶系统中, 多个CV系统/算法通常都在发挥作用。在这些情况下,对并行处理的需求很高,这导致了对底层计算机器的高压力。

如果同时使用多个神经网络,它们可能会分享共同的系统存储,并相互竞争共同的资源池。

在医学成像的情况下,计算机视觉系统的性能是 由经验丰富的放射科医生和临床专家来判断的,他们了解图像背后的病理。此外,在大多数情况下,任务涉及识别流行率极低的罕见疾病

这使得训练数据变得稀疏和稀少,也就是说,找不到足够的训练图像。因此,深度学习(DL)架构必须通过增加巧妙的处理和架构复杂性来弥补这一点。

为什么TensorFlow用于CV?

TensorFlow是一个被广泛使用和高度评价的来自谷歌的开源Python包,它使构建计算机视觉深度学习模型变得直接和简单。从它的官方网站上看。

"它有一个全面的、灵活的工具、库和社区资源的生态系统,让研究人员推动ML的最先进技术,让开发人员轻松构建和部署ML驱动的应用程序。"

随着TensorFlow 2.0的发布和Keras库的集成作为高级API,很容易堆叠神经元层,构建和训练足够复杂的深度学习架构。

EXX-Blog-CV-using-TF-1.jpg


轻松构建模型
使用直观的高级别API(如Keras)轻松构建和训练ML模型,以便立即进行模型迭代和轻松调试

强大的ML生产在任何地方
无论你使用何种编程语言,都可以轻松地在云端、内部和设备上训练和部署模型。

强大的研究
简单而灵活的架构,将新的想法从概念转化为代码。满怀信心地发布最先进的模型

当然,现在,TensorFlow可以用来为各种应用建立深度学习模型,包括。

  • 对象检测
  • 场景分割
  • 合成图像的生成对抗网络
  • 用于图像压缩的自动编码器
  • 推荐系统

然而,在这篇文章中,我们专注于使用TensorFlow的卷积 神经网络(CNN)构建一个简单的物体分类任务的代码和实践案例。

这涵盖了TensorFlow的所有基本组件,如层、优化器、误差函数、训练选项、超参数调整等。

物体分类任务的实践案例

深度学习任务和模型训练广泛地受益于像游戏处理单元(GPU)这样的专门硬件。

通用CPU在对大量数据进行操作时很吃力,例如 有几万或几十万浮点数的 矩阵进行线性代数操作

在引擎盖下,深度神经网络主要由矩阵乘法和向量加法等操作组成。GPU被开发出来(主要是为了迎合视频游戏行业),使用数千个微小的计算核心处理大规模的并行计算

它们还具有较大的内存带宽,以处理这些计算在神经网络通过数百个历时进行训练时所需的快速数据流(处理单元到缓存到较慢的主内存,再返回)。这使它们成为处理计算机视觉任务的计算负荷的理想商品硬件

使用和检查GPU

有各种途径可以将GPU用于深度学习任务。购买裸机服务器或工作站对那些寻求峰值定制能力的人来说是有益的。从AWS或GCP的云端租借GPU计算资源,对于那些用有限的数据来运行短的会议是非常好的。或者使用免费的(但有限的)资源,如Google Colaboratory。数据集越大,模型越好,但在这个例子中,我们使用最后一个选项Google Colab。

我们首先测试是否有GPU用于训练。

import tensorflow as tf
device_name = tf.test.gpu_device_name()

if device_name != '/device:GPU:0':
  raise SystemError('GPU device not found')

print('Found GPU at: {}'.format(device_name))

获取数据集

我们直接将数据集下载到本地环境(Google Colab的),代码如下。如果你在你的本地机器上工作(并且已经保存了文件),那么相应地修改代码。

**!**wget --no-check-certificate \ **https://storage.**googleapis**.**com/laurencemoroney-blog**.**appspot**.**com/horse-or-human**.**zip \

-O /tmp/horse-or-human**.**zip

访问压缩文件的内容

下面的python代码将使用操作系统库来使用操作系统库,让你访问文件系统和zipfile库,允许你解压数据。

import os
import zipfile

local_zip = '/tmp/horse-or-human.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')

zip_ref.extractall('/tmp/horse-or-human')
zip_ref.close()

.zip的内容被解压缩到基础目录/tmp/horse-or-human ,其中又分别包含马和人的子目录。简而言之,训练集是用来告诉神经网络模型*"这就是马*的样子"、"这就是人的样子 "等的数据。

请注意,我们并没有明确地将这些图像标记为马或人。稍后我们将看到一个叫做ImageGenerator的东西被使用--它被编码为从子目录中读取图像,并根据该子目录的名称自动标注。因此,举例来说,我们将有一个 "训练 "目录,其中包含一个 "马 "目录和一个 "人 "目录。ImageGenerator将为你适当地标注图像,减少编码步骤。

让我们来定义这些目录中的每一个。

# Directory with our training horse pictures
train_horse_dir = os.path.join('/tmp/horse-or-human/horses')

# Directory with our training human pictures
train_human_dir = os.path.join('/tmp/horse-or-human/humans')

下面的代码将让我们看到马匹和人类训练目录中的文件名是什么样子。

train_horse_names = os.listdir(train_horse_dir)
print(train_horse_names[:10])

train_human_names = os.listdir(train_human_dir)
print(train_human_names[:10])

我们可以找出目录中的马和人的图片总数。

print('total training horse images:', len(os.listdir(train_horse_dir)))
print('total training human images:', len(os.listdir(train_human_dir)))

现在让我们看一下几张图片,以便更好地了解它们的样子。我们首先配置一下matplot 参数。

<a data-re-name="format" data-dropdown="true" href="https://app.contentstack.com/#" alt="Format" rel="format" role="button" aria-label="Format" tabindex="-1" data-re-icon="true"></a>
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

# Parameters for our graph; we'll output images in a 4x4 configuration
nrows = 4
ncols = 4

# Index for iterating over images
pic_index = 0

现在,显示一批8张马和8张人的图片。我们可以在Jupyter笔记本单元中重新运行以下代码,每次都能看到一批新的图片。

# Set up matplotlib fig, and size it to fit 4x4 pics
fig = plt.gcf()

fig.set_size_inches(ncols * 4, nrows * 4)

pic_index += 8
next_horse_pix = [os.path.join(train_horse_dir, fname) 
                for fname in train_horse_names[pic_index-8:pic_index]]

next_human_pix = [os.path.join(train_human_dir, fname) 
                for fname in train_human_names[pic_index-8:pic_index]]

for i, img_path in enumerate(next_horse_pix+next_human_pix):
  # Set up subplot; subplot indices start at 1
  sp = plt.subplot(nrows, ncols, i + 1)
  sp.axis('Off') # Don't show axes (or gridlines)

  img = mpimg.imread(img_path)
  plt.imshow(img)

plt.show()

从零开始构建架构

首先,导入TensorFlow库。

import tensorflow as tf

然后,我们添加卷积层,并将最终结果平铺到密集连接层中。最后,我们添加密集连接层。

注意: 我们面临的是一个两类分类问题,即二进制分类问题;我们将用一个sigmoid激活来结束我们的网络,这样我们的网络的输出将是一个介于0和1之间的单一标量,编码当前图像是1类(而不是0类)的概率。

model = tf.keras.models.Sequential([
# Note the input shape is the desired size of the image 300x300 with 3 bytes color

# This is the first convolution
tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(300, 300, 3)),
tf.keras.layers.MaxPooling2D(2, 2),

# The second convolution
tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),

# The third convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),

# The fourth convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),

# The fifth convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),

# Flatten the results to feed into a DNN
tf.keras.layers.Flatten(),

# 512 neuron hidden layer
tf.keras.layers.Dense(512, activation='relu'),

# Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('horses') and 1 for the other ('humans')
tf.keras.layers.Dense(1, activation='sigmoid')
])

注意使用tf.keras API来建立模型。model.summary() 方法的调用打印了一个神经网络的摘要。

输出形状 "一栏显示了你的特征图的大小在每个连续的层中是如何演变的。卷积层由于填充而使特征图的大小减少了一些,而每个池化层的尺寸都减半。

接下来,我们将配置模型训练的规格。我们将用binary_crossentropy loss 训练我们的模型,因为这是一个二元分类问题,我们的最终激活是一个sigmoid。我们将使用rmsprop 优化器,学习率为0.001

在训练期间,我们要监控分类的准确性。注意:在这种情况下,使用RMSprop优化算法随机梯度下降(SGD)更好,因为rmsprop ,为我们自动调整学习率。

其他优化器,如AdamAdagrad,也会在训练过程中自动调整学习率,在这里同样适用。

from tensorflow.keras.optimizers import RMSprop

model.compile(loss='binary_crossentropy',
              optimizer=RMSprop(lr=0.001),
              metrics=['acc'])

数据预处理

让我们设置数据生成器,读取源文件夹中的图片,将其转换为float32张量,并将其(连同其标签)送入我们的网络。我们将有一个生成器用于训练图片,一个用于验证图片。我们的生成器将产生一批大小为300x300的图像和它们的标签(二进制)。

你可能已经知道,进入神经网络的数据通常应该以某种方式进行规范化处理,以使其更适合于网络的处理。(将原始像素输入神经网络是不常见的)。

在我们的案例中,我们将通过将像素值归一化到[0, 1]范围来预处理我们的图像(最初所有的值都在[0, 255]范围)。

在Keras中,这可以使用rescale参数来完成。

keras.preprocessing.image.ImageDataGenerator 

这个ImageDataGenerator类允许你通过.flow(data, labels).flow_from_directory(directory)来实例化增强的图像批次(及其标签)的生成器。

然后这些生成器可以与接受数据生成器作为输入的Keras模型方法一起使用。fit_generator, evaluate_generator,和predict_generator

from tensorflow.keras.preprocessing.image import ImageDataGenerator

# All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1/255)

# Flow training images in batches of 128 using train_datagen generator
train_generator = train_datagen.flow_from_directory(
        '/tmp/horse-or-human/', # This is the source directory for training images
        target_size=(300, 300), # All images will be resized to 300x300
        batch_size=128,
        # Since we use binary_crossentropy loss, we need binary labels
        class_mode='binary')

训练和准确率图

让我们训练15个epochs -- 这可能需要几分钟的时间在典型的Google Colab硬件上运行。损失和准确率是训练进展的一个重要标志。它是对训练数据的分类进行猜测,然后对照已知的标签进行测量,计算出结果。准确率是指正确预测的分数/百分比。

history = model.fit_generator(
      train_generator,
      steps_per_epoch=8,  
      epochs=15,
      verbose=2)

下面的代码将帮助我们绘制准确率图,即准确率是如何随着重复训练(通过网络来回传递图像) epochs而提高的。

plt.plot(history.history['acc'],c='k',lw=2)
plt.grid(True)
plt.title("Training accuracy with epochs\n",fontsize=18)
plt.xlabel("Training epochs",fontsize=15)
plt.ylabel("Training accuracy",fontsize=15)
plt.show()

预测

现在让我们来看看如何使用该模型实际运行预测。这段代码将允许你从你的文件系统中选择1个或更多的文件,然后它将上传这些文件并通过模型运行它们,表明该物体是马还是人。为此,我们使用google.colab 类中的files.upload() 方法。

注意:请从互联网上下载一些马和人的图片,并将它们保存在你的本地硬盘上,因为你将需要上传它们来测试模型。你可以一次上传多张图片。

import numpy as np
from google.colab import files
from keras.preprocessing import image

uploaded = files.upload()

for fn in uploaded.keys():
  # predicting images
  path = '/content/' + fn
  img = image.load_img(path, target_size=(300, 300))
  plt.imshow(img)
  plt.show()
  x = image.img_to_array(img)
  x = np.expand_dims(x, axis=0)

images = np.vstack([x])
  classes = model.predict(images, batch_size=10)
  if classes[0]>0.5:
    print(fn + " shows a human image")
  else:
    print(fn + " shows a horse image")

这里有一些测试图像的例子。如果训练得当,网络将预测第一张图片为 "人 "类,其他三张为 "马 "类。

该模型有些是对的,但有些是错的。该模型在最后一张图片中犯错的可能性很大。我们鼓励你用你的图像进行测试,检查模型的性能。

使用TensorFlow的计算机视觉

这篇文章涵盖了使用TensorFlow和Keras框架为一个物体分类任务建立一个具有卷积神经网架构的计算机视觉模型。

文章提供了实践代码,并且在这个例子中涵盖了TensorFlow的所有重要组件--层、模型编译、优化器、损失函数、甚至图像生成器类。以此为起点,利用TensorFlow探索更多的CV任务,如物体检测、语义分割等。

计算机 数据结构 深度学习 机器学习 TensorFlow 数据(计算) 网络 神经网络 神经网络(杂志) 系统

经Kevin Vu许可发表于DZone。在此查看原文。

DZone贡献者所表达的观点属于他们自己。

DZone上的热门文章


评论

AI 合作伙伴资源