如果您仔细查看 run_inference_on_image 和整个 classify_image.py 脚本,它并没有定义模型。它只是一个运行脚本,从磁盘加载 预训练模型(参见 create_graph)并根据某些约定执行它(run_inference_on_image loos 用于名为 softmax:0 的张量)。
tutorial 声明相同:
classify_image.py 在程序第一次运行时从 tensorflow.org 下载训练好的模型。
因此,您问题的确切答案实际上取决于您实际决定运行的模型(例如,您可以提供自己的模型)。我将重点介绍此脚本的默认选择,即Inception model(请参阅DATA_URL 常量)。顺便说一句,您也可以使用更新的预训练 Inception v3 model (GitHub issue)。
旁注:this implementation 的确切源代码未公布,但我们可以在tf slim 中查看同一网络的最新实现。图中的命名略有不同,但模型实际上是相同的。
一张图片中的整个模型看起来像this。本质上,它是一长串初始模块,由带有各种过滤器的卷积层组成。 inception模块v3的变种是:
这里每个a x b 框表示一个卷积层,过滤器大小为[a, b]。它看起来很吓人,但如果你多年来一直关注history of its development,它就会开始变得有意义。
上图翻译成如下代码(n=7):
with tf.variable_scope(end_point):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, depth(128), [1, 1], scope='Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, depth(128), [1, 7],
scope='Conv2d_0b_1x7')
branch_1 = slim.conv2d(branch_1, depth(192), [7, 1],
scope='Conv2d_0c_7x1')
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, depth(128), [1, 1], scope='Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, depth(128), [7, 1],
scope='Conv2d_0b_7x1')
branch_2 = slim.conv2d(branch_2, depth(128), [1, 7],
scope='Conv2d_0c_1x7')
branch_2 = slim.conv2d(branch_2, depth(128), [7, 1],
scope='Conv2d_0d_7x1')
branch_2 = slim.conv2d(branch_2, depth(192), [1, 7],
scope='Conv2d_0e_1x7')
with tf.variable_scope('Branch_3'):
branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
branch_3 = slim.conv2d(branch_3, depth(192), [1, 1],
scope='Conv2d_0b_1x1')
net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3])
至于您对“线性代数运算”的建议,请注意卷积层与线性层不同(有关详细信息,请参阅 CS231n tutorial),尽管存在可归结为矩阵乘法的高效 GPU 实现。
如您所见,仅使用低级操作从头开始重复相同的模型需要大量代码(tf slim 中的full source code 是 600 行,它实际上由高级抽象)。如果你想自己从预训练状态重新训练它,像这样导入已经构建的模型会更简单:
from tensorflow.contrib.slim.python.slim.nets.inception_v3 import inception_v3
...
inputs = tf.random_uniform((batch_size, height, width, 3))
logits, end_points = inception_v3(inputs, num_classes)