Tensorflow教程2:使用卷积神经网络的图像分类器

       在本Tensorflow教程中,我们将使用Tensorflow构建基于卷积神经网络的图像分类器。如果您刚刚开始使用Tensorflow,那么最好在这里阅读基本的Tensorflow教程

       为了演示如何构建基于卷积神经网络的图像分类器,我们将构建一个六层神经网络,该网络将识别并分离出狗的图像和猫的图像。我们将建立的这个网络是一个非常小的网络,您也可以在CPU上运行它。擅长进行图像分类的传统神经网络具有更多参数,并且如果在CPU上进行训练会花费大量时间。但是,在本文中,我的目的是向您展示如何使用Tensorflow而不是参与ILSVRC来构建真实世界的卷积神经网络。在开始Tensorflow教程之前,让我们介绍卷积神经网络的基础知识。如果您已经熟悉conv-nets(并称之为conv-nets),则可以转到第2部分,即Tensorflow教程。

第1部分:卷积神经网络(CNN)的基础知识
       

        神经网络本质上是解决优化问题的数学模型。 它们由神经元组成,神经元是神经网络的基本计算单元。 一个神经元接受一个输入(例如x),对其进行一些计算(例如:将它与变量w相乘,然后加上另一个变量b)以产生一个值(例如z = wx + b)。 该值传递给称为激活函数(f)的非线性函数,以产生神经元的最终输出(激活)。 激活功能有很多种。 Sigmoid是流行的激活功能之一,它是:

    用sigmoid作为激活功能的神经元称为sigmoid神经元。 根据激活功能,神经元被命名,并且它们有很多种类,如RELU,TanH等(请记住)。 一个神经元可以连接到多个神经元,如下所示:

      在此示例中,您可以看到权重是连接的属性,即每个连接具有不同的权重值,而偏差是神经元的属性。 这是产生输出y的S形神经元的完整图片:

层数

     如果将神经元堆叠成一行,则称为层; 这是神经网络的下一个构建块。

      如您在上面看到的,绿色的神经元形成一层,这是网络的第一层,输入数据通过该层传递到网络。 同样,最后一层称为输出层,如红色所示。 输入和输出层之间的层称为隐藏层。 在此示例中,我们只有1个隐藏层以蓝色显示。 具有许多隐藏层的网络往往更准确,称为深度网络,因此,使用这些深度网络的机器学习算法称为深度学习。

图层类型
 

      通常,一层中的所有神经元都执行类似的数学运算,这就是该层获得其名称的方式(输入和输出层除外,因为它们很少进行数学运算)。 以下是您应该了解的最流行的图层类型:

卷积层

       卷积是一种数学运算,用于单个处理中以过滤信号,查找信号中的模式等。在卷积层中,所有神经元都将卷积运算应用于输入,因此称为卷积神经元。 卷积神经元中最重要的参数是滤镜大小,假设我们有一个滤镜大小为5 * 5 * 3的层。 另外,假设输入到卷积神经元的输入是3通道大小为32 * 32的输入图像。

         让我们从图像中选择一个5 * 5 * 3(彩色图像中通道数为3)大小的块,然后使用我们的过滤器(w)计算卷积(点积)。 这一卷积运算将得到一个数字作为输出。 我们还将在此输出上加上bias(b)。

        为了计算点积,必须使过滤器的第3维与输入中的通道数相同。 也就是说,当我们计算点积时,它是5 * 5 * 3大小的块与5 * 5 * 3大小的过滤器的矩阵相乘。

        我们将在整个输入图像上滑动卷积滤波器,以在整个图像上计算此输出,如下图所示:

        在这种情况下,我们一次将窗口滑动1个像素。 在某些情况下,人们会将窗户滑动超过1个像素。 此数字称为跨步。

         如果将所有这些输出连接为2D,我们将得到大小为28 * 28的输出激活图(您能想到为什么32 * 32的28 * 28的过滤器为5 * 5且步幅为1)。 通常,我们在一个卷积层中使用多个过滤器。 如果在示例中有6个过滤器,则输出大小为28 * 28 * 6。

       如您所见,每次卷积后,输出的大小都会减小(在这种情况下,我们将从32 * 32变为28 * 28)。 在具有多层结构的深度神经网络中,这种方式的输出将变得非常小,效果不佳。 因此,通常的做法是在输入层的边界上添加零,以使输出与输入层的大小相同。 因此,在此示例中,如果我们在输入层的两侧添加大小为2的填充,则输出层的大小将为32 * 32 * 6,这从实现目的出发也很有效。 假设您有一个大小为N * N的输入,过滤器大小为F,您将S作为步幅,并在输入中添加了大小为P的0填充。那么,输出大小将为:

2.池化层
 

     池化层通常在卷积层之后立即使用,以减小空间大小(仅宽度和高度,而不是深度)。 这减少了参数的数量,因此减少了计算。 另外,较少的参数可以避免过度拟合(现在不必担心,稍后会介绍)。 池化的最常见形式是最大池化,其中我们采用大小为F * F的过滤器,并对图像的F * F大小的部分进行最大运算。

      如果您用平均值代替最大值,则称为平均值池,但是这种方法不太流行。

      如果您的输入大小为w1 * h1 * d1,并且过滤器的大小为f * f,步幅为S。那么输出大小w2 * h2 * d2将为:

        w2 =(w1-f)/ S +1

       h2 =(h1-f)/ S +1

      d2 = d1

       最常见的合并是使用步长为2的大小为2 * 2的过滤器完成的。您可以使用上述公式进行计算,实际上可以将输入的大小减少一半。

3.全连接层

        如果一层中的每个神经元都接收到前一层中所有神经元的输入,则该层称为完全连接层。 该层的输出通过矩阵相乘,然后是偏置偏移来计算。

了解培训过程:
       深度神经网络不过是某种程度上可以模仿人脑的智能数学模型。 当我们尝试训练神经网络时,我们需要做两个基本的事情:

网络架构

     在设计神经网络的体系结构时,您必须决定:如何布置图层?使用哪一层?每层等要使用多少个神经元?设计体系结构是一个稍微复杂和高级的主题,需要大量研究。有许多标准体系结构可以很好地解决许多标准问题。例如AlexNet,GoogleNet,InceptionResnet,VGG等。一开始,您应该只使用标准的网络体系结构。在拥有丰富的神经网络经验之后,您可以开始设计网络。因此,让我们现在不必担心。

正确的权重/参数

        一旦确定了网络的架构;第二大变量是权重(w)和偏差(b)或网络的参数。培训的目的是获得所有这些参数的最佳可能值,以可靠地解决问题。例如,当我们试图在狗和猫之间建立分类器时,我们正在寻找找到这样的参数:对于所有的狗图像和猫的可能性,输出层将狗的概率设为1(或至少高于猫)对于猫的所有图像,均为1((或至少高于狗)。

      您可以使用称为向后传播的过程找到最佳的参数集,即从一组随机的参数开始并不断更改这些权重,以便对于每个训练图像我们都能获得正确的输出。有许多优化器方法可以在数学上快速找到正确的权重来更改权重。 GradientDescent就是这样一种方法(改变梯度的向后传播和优化器方法是一个非常复杂的主题。但是,由于Tensorflow会处理它,我们现在不必担心它)。

       因此,假设我们从参数的一些初始值开始,并为dog提供了1个训练图像(实际上是将多个图像馈入在一起),并且将网络的输出计算为0.1(对于它来说是狗)和0.9(对于它来说是a)猫。现在,我们进行向后传播以缓慢更改参数,以使该图像成为狗的可能性在下一次迭代中增加。有一个变量用于控制我们在训练期间更改网络参数的速度,即学习率。如果您考虑一下,我们希望通过网络最大化总的正确分类,即我们关心整个训练集;我们要进行这些更改,以使网络正确分类的数量增加。因此,我们定义了一个称为成本的数字,该数字指示培训是否朝着正确的方向发展。通常,成本的定义方式是:随着成本的降低,网络的准确性也随之提高。因此,我们关注成本,并不断进行多次向前和向后传播(有时为数十万次),直到成本停止下降为止。有许多定义成本的方法。简单的一种是均方根成本。假设yprediction是包含所有训练图像的网络输出的向量,而yactual是包含这些标记图像的实际值(也称为基本事实)的向量。因此,如果我们最小化这两个变量之间的距离,那么它将很好地指示训练。因此,我们将成本定义为所有图像的平均距离:

        这是一个非常简单的成本示例,但是在实际培训中,我们使用了更为复杂的成本度量,例如交叉熵成本。但是Tensorflow会执行其中的许多费用,因此我们现在不必担心这些费用的细节。

      训练完成后,这些参数和体系结构将保存在二进制文件(称为模型)中。在生产设置中,当我们获得新的狗/猫图像进行分类时,我们将此模型加载到相同的网络体系结构中,并计算出新图像成为猫/狗的可能性。这称为推断或预测。

      为了简化计算,并非所有训练数据都立即馈入网络。而是说,我们总共有1600张图片,我们将它们分成小批量,例如16或32号,称为“批处理大小”。因此,将需要100或50轮(迭代)才能将完整的数据用于训练。这称为一个时期,即在一个时期中,网络一次看到所有训练图像。还有很多其他事情可以提高准确性,但不要一次担心所有事情。

第2部分:Tensorflow教程->构建基于神经网络的小型图像分类器

       我们将在本教程中实现的网络更小,更简单(比用于解决实际问题的网络更简单),因此您也可以在cpu上进行训练。 在训练时,来自两个类别(狗/猫)的图像都被馈送到卷积层,然后是另外两个卷积层。 卷积层之后,我们将输出展平并在最后添加两个完全连接的层。 第二个完全连接的层只有两个输出,代表图像是猫还是狗的可能性。

a)先决条件
 

      i)OpenCV:我们使用openCV读取猫/狗的图像,因此您必须安装它。

      ii)形状功能:

如果您在TF中具有多维Tensor,则可以通过执行以下操作获得形状:

a = tf.truncated_normal([16,128,128,3])
sess = tf.Session()
sess.run(tf.initialize_all_variables())
sess.run(tf.shape(a))

       输出将是:array([16,128,128,3],dtype = int32)

        您可以将其重塑为形状为[16 128 * 128 * 3] = [16 49152]的新2D张量。

b=tf.reshape(a,[16,49152])
sess.run(tf.shape(b))

         输出:array([16,49152],dtype = int32)

        iii)Softmax:是将包含实数值的K维向量'x'转换为(0,1)范围之和为1的相同形状的实数值向量的函数。我们将softmax函数应用于 卷积神经网络的输出,以便将输出转换为每个类别的概率。

b)读取输入

    我已经从Kaggle数据集中使用了2000张狗和猫的图像,但是您可以使用计算机上包含不同种类对象的n个图像文件夹。通常,我们将输入数据分为3部分:

   训练数据:我们将使用80%(即0张图片)进行训练。
    验证数据:将使用20%的图像进行验证。这些图像从训练数据中取出,以在训练过程中独立地计算准确性。
    测试集:单独的独立数据进行测试,其中包含约400张图像。有时是由于所谓的过度拟合;训练后,神经网络开始在训练数据(和非常相似的图像)上很好地工作,即成本变得很小,但对于其他图像却无法很好地工作。例如,如果您正在训练猫和狗之间的分类器,并且您从拍摄所有具有白色背景的图像的人那里获得训练数据。您的网络可能会在此验证数据集上很好地工作,但是如果您尝试在背景杂乱的图像上运行它,则很有可能会失败。因此,

classes = ['dogs', 'cats']
num_classes = len(classes)
 
train_path='training_data'
 
# validation split
validation_size = 0.2
 
# batch size
batch_size = 16
 
data = dataset.read_train_sets(train_path, img_size, classes, validation_size=validation_size)

       数据集是我创建的用于读取输入数据的类。 这是一个简单的python代码,可从提供的训练和测试数据文件夹中读取图像。

       我们训练的目的是为网络中所有在猫与狗之间进行分类的神经元学习权重/偏向的正确值。 这些权重的初始值可以是任何值,但如果采用正态分布(均值为零且方差较小),则效果会更好。 还有其他初始化网络的方法,但正态分布更为普遍。 让我们创建仅需指定形状即可快速创建初始权重的函数(请记住,在之前的文章中我们讨论过truncated_normal函数)。

def create_weights(shape):
    return tf.Variable(tf.truncated_normal(shape, stddev=0.05))
 
def create_biases(size):
    return tf.Variable(tf.constant(0.05, shape=[size]))

c)创建网络层

  i)在TensorFlow中构建卷积层
         

        tf.nn.conv2d函数可用于构建卷积层,该卷积层接受以下输入:

         输入=上一层的输出(激活)。这应该是一个4-D张量。通常,在第一个卷积层中,您传递大小为width * height * num_channels的n张图像,然后图像的大小为[n width height num_channels]

filter =定义过滤器的可训练变量。我们从随机正态分布开始,并学习这些权重。这是一个4D张量,其特定形状在网络设计中已预先定义。如果您的过滤器的大小为filter_size,并且输入的输入具有num_input_channels个,并且当前层中有num_filters个过滤器,则过滤器将具有以下形状:

      [filter_size filter_size num_input_channels num_filters]

            strides =定义进行卷积时要移动滤镜多少。在此函数中,其张量必须大于等于4,即[batch_stride x_stride y_stride depth_stride]。 batch_stride始终为1,因为您不想跳过批处理中的图像。 x_stride和y_stride大致相同,选择是网络设计的一部分,在我们的示例中将其用作1。由于您不会沿深度跳过,depth_stride始终设置为1。

      padding = SAME表示我们将0输入填充,以使输出x,y尺寸与输入尺寸相同。

     卷积后,我们添加该神经元的偏差,这也是可学习/可训练的。同样,我们从随机正态分布开始,并在训练过程中学习这些值。

    现在,我们使用tf.nn.max_pool函数应用最大池,该函数的签名与conv2d函数的签名非常相似。

tf.nn.max_pool(value=layer,
                               ksize=[1, 2, 2, 1],
                               strides=[1, 2, 2, 1],
                               padding='SAME')

        请注意,我们将k_size / filter_size用作2 * 2,在x和y方向上的步幅均为2。 如果使用前面提到的公式(w2 =(w1-f)/ S +1; h2 =(h1-f)/ S +1),我们可以看到输出恰好是输入的一半。 这些是最大池化的最常用值。

      最后,我们使用RELU作为激活函数,该函数仅获取max_pool的输出并使用tf.nn.relu应用RELU

        所有这些操作都在单个卷积层中完成。 让我们创建一个函数来定义完整的卷积层。

def create_convolutional_layer(input,
               num_input_channels, 
               conv_filter_size,        
               num_filters):  
    
    ## We shall define the weights that will be trained using create_weights function.
    weights = create_weights(shape=[conv_filter_size, conv_filter_size, num_input_channels, num_filters])
    ## We create biases using the create_biases function. These are also trained.
    biases = create_biases(num_filters)
 
    ## Creating the convolutional layer
    layer = tf.nn.conv2d(input=input,
                     filter=weights,
                     strides=[1, 1, 1, 1],
                     padding='SAME')
 
    layer += biases
 
    ## We shall be using max-pooling.  
    layer = tf.nn.max_pool(value=layer,
                            ksize=[1, 2, 2, 1],
                            strides=[1, 2, 2, 1],
                            padding='SAME')
    ## Output of pooling is fed to Relu which is the activation function for us.
    layer = tf.nn.relu(layer)
 
    return layer

ii)展平层

     卷积层的输出是多维张量。 我们想将其转换为一维张量。 这是在展平层中完成的。 我们只需使用重塑操作即可创建一维张量,如下所示:

def create_flatten_layer(layer):
    layer_shape = layer.get_shape()
    num_features = layer_shape[1:4].num_elements()
    layer = tf.reshape(layer, [-1, num_features])
 
    return layer

 

iii)全连接层

       现在,让我们定义一个函数来创建完全连接的图层。 与其他任何层一样,我们将权重和偏差声明为随机正态分布。 在完全连接的层中,我们接受所有输入,并对它执行标准的z = wx + b操作。 有时您也想向其中添加非线性度(RELU)。 因此,我们添加一个条件,允许调用者将RELU添加到图层。

def create_fc_layer(input,          
             num_inputs,    
             num_outputs,
             use_relu=True):
    
    #Let's define trainable weights and biases.
    weights = create_weights(shape=[num_inputs, num_outputs])
    biases = create_biases(num_outputs)
 
    layer = tf.matmul(input, weights) + biases
    if use_relu:
        layer = tf.nn.relu(layer)
 
    return layer

至此,我们已经完成了网络构建模块的定义。

iv)占位符和输入

       现在,让我们创建一个占位符,以保存输入的训练图像。 所有输入图像都在dataset.py文件中读取,并调整为128 x 128 x 3大小。 输入占位符x以[None,128,128,3]的形式创建。 第一个尺寸为无表示您可以向其传递任意数量的图像。 对于此程序,我们将以16个批次传递图像,即形状将为[16 128 128 3]。 同样,我们创建一个占位符y_true来存储预测。 对于每个图像,我们有两个输出,即每个类的概率。 因此,y_pred的形状为[None 2](对于批量大小16,它将为[16 2]。

x = tf.placeholder(tf.float32, shape=[None, img_size,img_size,num_channels], name='x')
 
y_true = tf.placeholder(tf.float32, shape=[None, num_classes], name='y_true')
y_true_cls = tf.argmax(y_true, dimension=1)

v)网络设计

        我们使用上面定义的功能来创建网络的各个层。

layer_conv1 = create_convolutional_layer(input=x,
               num_input_channels=num_channels,
               conv_filter_size=filter_size_conv1,
               num_filters=num_filters_conv1)
 
layer_conv2 = create_convolutional_layer(input=layer_conv1,
               num_input_channels=num_filters_conv1,
               conv_filter_size=filter_size_conv2,
               num_filters=num_filters_conv2)
 
layer_conv3= create_convolutional_layer(input=layer_conv2,
               num_input_channels=num_filters_conv2,
               conv_filter_size=filter_size_conv3,
               num_filters=num_filters_conv3)
          
layer_flat = create_flatten_layer(layer_conv3)
 
layer_fc1 = create_fc_layer(input=layer_flat,
                     num_inputs=layer_flat.get_shape()[1:4].num_elements(),
                     num_outputs=fc_layer_size,
                     use_relu=True)
 
layer_fc2 = create_fc_layer(input=layer_fc1,
                     num_inputs=fc_layer_size,
                     num_outputs=num_classes,
                     use_relu=False)

vi)预测

    如上所述,您可以通过将softmax应用于完全连接层的输出来获得每个类别的概率。

     y_pred = tf.nn.softmax(layer_fc2,name =“ y_pred”)

    y_pred包含每个输入图像的每个类别的预测概率。 具有较高概率的类别是网络的预测。 y_pred_cls = tf.argmax(y_pred,维= 1)

     现在,让我们定义将成本最小化以达到最佳权重值的成本。 我们将使用一个简单的成本,该成本将通过Tensorflow函数softmax_cross_entropy_with_logits计算得出,该函数将最后一个完全连接的层的输出和实际标签一起计算出cross_entropy,其平均值将为我们提供成本。

cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=layer_fc2,
                                                    labels=y_true)
cost = tf.reduce_mean(cross_entropy)

VII)优化

      Tensorflow实现了大多数优化功能。 我们将使用AdamOptimizer进行梯度计算和权重优化。 我们将指定我们试图以0.0001的学习率来最小化成本。

      优化器= tf.train.AdamOptimizer(learning_rate = 1e-4).minimize(cost)

       如您所知,如果我们在session.run()中运行优化器操作,为了计算成本值,则必须运行整个网络,并且我们将在feed_dict中传递训练图像(这有意义吗? 关于,您需要什么变量来计算成本并不断增加代码)。 训练图像在每次迭代中以16(batch_size)的批次传递。

batch_size = 16
 
x_batch, y_true_batch, _, cls_batch = data.train.next_batch(batch_size)
 
feed_dict_train = {x: x_batch,
                           y_true: y_true_batch}
 
session.run(optimizer, feed_dict=feed_dict_tr)

        其中,next_batch是dataset.py文件中的一个简单python函数,该函数返回要传递的下16张图像进行训练。 类似地,我们将图像的验证批独立地传递到另一个session.run()调用中。

x_valid_batch, y_valid_batch, _, valid_cls_batch = data.valid.next_batch(train_batch_size)
 
feed_dict_val = {x: x_valid_batch,
                      y_true: y_valid_batch}
 
val_loss = session.run(cost, feed_dict=feed_dict_val)

        请注意,在这种情况下,我们在session.run()中通过一批验证图像而不是训练图像传递成本。 为了计算成本,必须执行整个网络(3个卷积+1平坦化+2个fc层)以生成layer_fc2(这是计算cross_entropy,因此需要成本)。 但是,与训练相反,这次优化器= tf.train.AdamOptimizer(learning_rate = 1e-4).minimize(cost)将不会运行(因为我们只需要计算成本)。 这就是改变梯度和权重的原因,并且在计算上非常昂贵。 我们可以使用true标签(y_true)和预测标签(y_pred)计算验证集的准确性。

correct_prediction = tf.equal(y_pred_cls, y_true_cls)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

       我们可以通过在session.run()中传递精度并在feed_dict中提供验证图像来计算验证精度。

        val_acc = session.run(准确性,feed_dict = feed_dict_validate)

       同样,我们还报告了训练图像的准确性。

       acc = session.run(准确性,feed_dict = feed_dict_train)

      由于训练图像和标签一起用于训练,因此一般而言训练精度将高于验证精度。 我们报告训练准确性,以了解我们至少在朝着正确的方向发展,并且至少在改善训练数据集中的准确性。 在每个纪元之后,我们报告准确性数字,并使用Tensorflow中的saver对象保存模型。

saver.save(session, 'dogs-cats-model')
def train(num_iteration):
    global total_iterations
    
    for i in range(total_iterations,
                   total_iterations + num_iteration):
 
        x_batch, y_true_batch, _, cls_batch = data.train.next_batch(batch_size)
        x_valid_batch, y_valid_batch, _, valid_cls_batch = data.valid.next_batch(batch_size)
 
        
        feed_dict_tr = {x: x_batch,
                           y_true: y_true_batch}
        feed_dict_val = {x: x_valid_batch,
                              y_true: y_valid_batch}
 
        session.run(optimizer, feed_dict=feed_dict_tr)
 
        if i % int(data.train.num_examples/batch_size) == 0: 
            val_loss = session.run(cost, feed_dict=feed_dict_val)
            epoch = int(i / int(data.train.num_examples/batch_size))    
            
            show_progress(epoch, feed_dict_tr, feed_dict_val, val_loss)
            saver.save(session, 'dogs-cats-model') 
 
 
    total_iterations += num_iteration

          该代码有点长,因为它是一个真实的示例。 因此,请转到此处,克隆代码并运行train.py文件以开始培训。 这是输出的样子:

        这是一个小型网络,并不是构建图像分类器的最新技术,但对于刚开始学习的人尤其有用。 对于我们的培训,我们在验证集上获得了80%以上的准确性。 在训练过程中保存模型时,我们将使用它来运行自己的图像。

预测

      完成培训后,您将注意到文件夹中有许多新文件:

      狗猫模型。元
      狗猫模型.data-00000-of-00001
     狗猫模型索引
      检查站
     文件dogs-cats-model.meta包含完整的网络图,我们以后可以使用它来重新创建图。 我们将使用Tensorflow提供的保护程序对象来执行此操作。

saver = tf.train.import_meta_graph('flowers-model.meta')

       为了获得网络的预测,我们需要以与训练相同的方式读取和预处理输入图像,获得y_pred在图上并将新图像传递给feed dict。 因此,让我们这样做:

image = cv2.imread(filename)
# Resizing the image to our desired size and
# preprocessing will be done exactly as done during training
image = cv2.resize(image, (image_size, image_size), cv2.INTER_LINEAR)
images.append(image)
images = np.array(images, dtype=np.uint8)
images = images.astype('float32')
images = np.multiply(images, 1.0/255.0) 
#The input to the network is of shape [None image_size image_size num_channels]. Hence we reshape.
x_batch = images.reshape(1, image_size,image_size,num_channels)
 
 
graph = tf.get_default_graph()
 
y_pred = graph.get_tensor_by_name("y_pred:0")
 
## Let's feed the images to the input placeholders
x= graph.get_tensor_by_name("x:0") 
y_true = graph.get_tensor_by_name("y_true:0") 
y_test_images = np.zeros((1, 2)) 
 
feed_dict_testing = {x: x_batch, y_true: y_test_images}
result=sess.run(y_pred, feed_dict=feed_dict_testing)

      最后,我们可以使用预测脚本运行新的狗/猫

python predict.py test_dog.jpg
[[ 0.99398661  0.00601341]]

     输出包含输入图像是狗还是猫的概率。 在此示例中,成为狗的可能性比猫的可能性高得多。

     恭喜你! 您已经了解了如何使用卷积神经网络构建和训练图像分类器。

       训练有素的模型和数据:在git存储库中,我只为每个类添加了500张图像。 但是,即使训练像样的分类器,也要花费500多张狗/猫的图像。 因此,我已经在每个班级的2400张图像上训练了该模型。 您可以从此处下载这些图像。 此Mini-cat-dog-dataset是Kaggle Dog-Cat数据集的子集,并不归我们所有。 您也可以使用此处提供的我训练有素的模型来生成预测。

      完整的代码在这里。 请在下面的评论中让我知道您的问题和反馈。 这些评论和反馈是我创建更多教程的动力。

 

       原文地址在这里

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 护眼 设计师:闪电赇 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值