Tensorflow實現GoogleInceptionNet_V3
引言:Google Inception Net首次出現在ILSVRC 2014的比賽中,並且有非常好的性能——top-5的錯誤率6.67%,後來又逐漸提出了Inception V2、Inception V3和Incepiton V4。本文實現的網絡結構爲Inception V3
- 相關閱讀:
VGGNet以及Tensorflow實現
AlexNet以及Tensorflow實現
ResNet_V2以及Tensorflow實現 - 模塊化方法:
本文將通過模塊化加註釋的方法,來實現GoogleInceptionNet,這樣可以幫助初學者快速讀懂其結果以及實現方法
- 定義網絡中經常用的函數的默認參數:inception_v3_arg_scope()
- 定義Inception v3網絡結構(前面部分):inception_v3_base()
- 定義Inception V3網絡的最後一部分:incepiton_v3()
- 定義耗時:time_tensorflow_run()
- GoogleInceptionNet結構:
- GoogleInceptionNet創新之處:
- 去除了最後的全連接層,用全局平均池化層(即將圖片尺寸變爲1x1)來取代他
- 根據Hebbian原理,多次使用1x1卷積核(即將相關性很高、在同一個空間位置但是不同通道的特徵連接起來)
- 使用了Inception Module提高了參數利用效率(上截圖Fig5-Fig7)
- 提出了著名的Batch Normalization(BN)方法,該方法可以讓大型卷積網絡的訓練速度加快很多倍,同時收斂後的分類內部準確率也可以得到大幅提高
- 引入Factorization into small convolutions的思想,將一個較大的2維卷積拆成兩個較小的一維卷積,如把3x3卷積拆成1x3和3x1兩個小卷積,不僅可以加速運算還可以減輕過擬合
導入包:
from datetime import datetime
import math
import time
import tensorflow as tf
slim = tf.contrib.slim
trunc_normal = lambda stddev: tf.truncated_normal_initializer(0.0, stddev) # 產生截斷的正態分佈
生成網絡中經常用的函數的默認參數:
# 生成網絡中經常用的函數的默認參數
def inception_v3_arg_scope(weight_decay = 4e-5,
stddev = 0.1,
batch_norm_var_collection = 'moving_vars'):
'''
weight_decay: L2正則weight_decay
stddev: 標準差
batch_norm_var_collection: 默認設置爲moving_vars
'''
# 定義batch normalization的參數字典
batch_norm_params = {
'decay': 0.9997,
'epsilon': 0.001,
'updates_collections': tf.GraphKeys.UPDATE_OPS,
'variables_collections': {
'beta': None,
'gamma': None,
'moving_mean': [batch_norm_var_collection],
'moving_variance': [batch_norm_var_collection],
}
}
# 使用slim.arg_scope對參數進行自動復賦值
with slim.arg_scope([slim.conv2d, slim.fully_connected],
weights_regularizer=slim.l2_regularizer(weight_decay)):
with slim.arg_scope(
[slim.conv2d],
weights_initializer=trunc_normal(stddev),
activation_fn=tf.nn.relu,
normalizer_fn=slim.batch_norm,
normalizer_params=batch_norm_params) as sc:
return sc
定義Inception v3網絡結構(前面部分):
# 定義Inception v3網絡結構
def inception_v3_base(inputs, scope = None):
end_points = {}
with tf.variable_scope(scope, 'InceptionV3', [inputs]):
'''
前面的卷積層結構 類似於VGGNet
input:299x299x3
output:35x35x192
'''
with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
stride = 1, padding = 'VALID'):
net = slim.conv2d(inputs, 32, [3, 3], stride = 2, scope = 'Conv2d_1a_3x3')
net = slim.conv2d(net, 32, [3, 3], scope = 'Conv2d_2a_3x3')
net = slim.conv2d(net, 64, [3, 3], padding = 'SAME', scope = 'Conv2d_2b_3x3')
net = slim.max_pool2d(net, [3, 3], stride = 2, scope = 'MaxPool_3a_3x3')
net = slim.conv2d(net, 80, [1, 1], scope = 'Conv2d_3b_1x1')
net = slim.conv2d(net, 192, [3, 3], scope = 'Conv2d_4a_3x3')
net = slim.max_pool2d(net, [3, 3], stride = 2, scope = 'MaxPool_5a_3x3')
with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
stride = 1, padding = 'SAME'):
'''
第一個Inception模塊組:第一個Module
input:35x35x192
output:35x35x256
'''
with tf.variable_scope('Mixed_5b'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 64, [1, 1], scope = 'Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 48, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope = 'Conv2d_0a_5x5')
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 64, [1, 1], scope = 'Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope = 'Conv2d_0b_3x3')
branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope = 'Conv2d_0c_3x3')
with tf.variable_scope('Branch_3'):
branch_3 = slim.avg_pool2d(net, [3, 3], scope = 'AvgPool_0a_3x3')
branch_3 = slim.conv2d(branch_3, 32, [1, 1], scope = 'Conv2d_0b_3x3')
# 將四個分支在channel上連起來 64 + 64 + 96 + 32 = 256
net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
'''
第一個Inception模塊組:第二個Module
input:35x35x256
output:35x35x288
'''
with tf.variable_scope('Mixed_5c'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 64, [1, 1], scope = 'Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 48, [1, 1], scope = 'Conv2d_0b_1x1')
branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope = 'Conv_1_0c_5x5')
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 64, [1, 1], scope = 'Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope = 'Conv2d_0b_3x3')
branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope = 'Conv2d_0c_3x3')
with tf.variable_scope('Branch_3'):
branch_3 = slim.avg_pool2d(net, [3, 3], scope = 'AvgPool_0a_3x3')
branch_3 = slim.conv2d(branch_3, 64, [1, 1], scope = 'Conv2d_0b_1x1')
# 64 + 64 + 96 + 64 = 288
net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
'''
第一個Inception模塊組:第三個Module(與第二個結構相同)
input:35x35x288
output:35x35x288
'''
with tf.variable_scope('Mixed_5d'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 48, [1, 1], scope='Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope='Conv2d_0b_5x5')
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0b_3x3')
branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0c_3x3')
with tf.variable_scope('Branch_3'):
branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
branch_3 = slim.conv2d(branch_3, 64, [1, 1], scope='Conv2d_0b_1x1')
# 64 + 64 + 96 + 64 = 288
net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
'''
第二個Inception模塊組:第一個Module
input:35x35x288
output:17x17x768
'''
with tf.variable_scope('Mixed_6a'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 384, [3, 3], stride = 2, padding = 'VALID', scope = 'Conv2d_1a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 64, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, 96, [3, 3], scope = 'Conv2d_0b_3x3')
branch_1 = slim.conv2d(branch_1, 96, [3, 3], stride = 2, padding = 'VALID', scope = 'Conv2d_1a_1x1')
with tf.variable_scope('Branch_2'):
branch_2 = slim.max_pool2d(net, [3, 3], stride = 2, padding = 'VALID', scope = 'MaxPool_1a_3x3')
# 384 + 96 + 288 = 768
net = tf.concat([branch_0, branch_1, branch_2], 3)
'''
第二個Inception模塊組:第二個Module
input:17x17x768
output:17x17x768
'''
with tf.variable_scope('Mixed_6b'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 192, [1, 1], scope = 'Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
# Factorization into small convolutions思想,減少參數的同時也減輕了過擬合
branch_1 = slim.conv2d(net, 128, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, 128, [1, 7], scope = 'Conv2d_0b_1x7')
branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope = 'Conv2d_0c_7x1')
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 128, [1, 1], scope = 'Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, 128, [7, 1], scope = 'Conv2d_0b_7x1')
branch_2 = slim.conv2d(branch_2, 128, [1, 7], scope = 'Conv2d_0c_1x7')
branch_2 = slim.conv2d(branch_2, 128, [7, 1], scope = 'Conv2d_0d_7x1')
branch_2 = slim.conv2d(branch_2, 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, 192, [1, 1], scope = 'Conv2d_0b_1x1')
# 192 + 192 + 192 + 192 = 768
net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
'''
第二個Inception模塊組:第三個Module
input:17x17x768
output:17x17x768
'''
with tf.variable_scope('Mixed_6c'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 192, [1, 1], scope = 'Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 160, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, 160, [1, 7], scope = 'Conv2d_0b_1x7')
branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope = 'Conv2d_0c_7x1')
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 160, [1, 1], scope = 'Conv2_0a_1x1')
branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope = 'Conv2d_0b_7x1')
branch_2 = slim.conv2d(branch_2, 160, [1, 7], scope = 'Conv2d_0c_1x7')
branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope = 'Conv2d_0d_7x1')
branch_2 = slim.conv2d(branch_2, 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, 192, [1, 1], scope = 'Conv2d_0b_1x1')
# 192 + 192 + 192 + 192 = 768
net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
'''
第二個Inception模塊組:第四個Module(與第三個結構相同)
input:17x17x768
output:17x17x768
'''
with tf.variable_scope('Mixed_6d'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 192, [1, 1], scope = 'Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 160, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, 160, [1, 7], scope = 'Conv2d_0b_1x7')
branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope = 'Conv2d_0c_7x1')
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 160, [1, 1], scope = 'Conv2_0a_1x1')
branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope = 'Conv2d_0b_7x1')
branch_2 = slim.conv2d(branch_2, 160, [1, 7], scope = 'Conv2d_0c_1x7')
branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope = 'Conv2d_0d_7x1')
branch_2 = slim.conv2d(branch_2, 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, 192, [1, 1], scope = 'Conv2d_0b_1x1')
# 192 + 192 + 192 + 192 = 768
net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
'''
第二個Inception模塊組:第四個Module(與第三個結構相同)
input:17x17x768
output:17x17x768
'''
with tf.variable_scope('Mixed_6e'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 192, [1, 1], scope = 'Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 192, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, 192, [1, 7], scope = 'Conv2d_0b_1x7')
branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope = 'Conv2d_0c_7x1')
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 192, [1, 1], scope = 'Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, 192, [7, 1], scope = 'Conv2d_0b_7x1')
branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope = 'Conv2d_0c_1x7')
branch_2 = slim.conv2d(branch_2, 192, [7, 1], scope = 'Conv2d_0d_7x1')
branch_2 = slim.conv2d(branch_2, 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, 192, [1, 1], scope = 'Conv2d_0b_1x1')
# 192 + 192 + 192 + 192 = 768
net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
end_points['Mixed_6e'] = net
'''
第三個Inception模塊組:第一個Module
input:17x17x768
output:8x8x1280
'''
with tf.variable_scope('Mixed_7a'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 192, [1, 1], scope = 'Conv2d_0a_1x1')
branch_0 = slim.conv2d(branch_0, 320, [3, 3], stride = 2, padding = 'VALID', scope = 'Conv2d_1a_3x3')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 192, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = slim.conv2d(branch_1, 192, [1, 7], scope = 'Conv2d_0b_1x7')
branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope = 'Conv2d_0c_7x1')
branch_1 = slim.conv2d(branch_1, 192, [3, 3], stride = 2, padding = 'VALID', scope = 'Conv2d_1a_3x3')
with tf.variable_scope('Branch_2'):
branch_2 = slim.max_pool2d(net, [3, 3], stride = 2, padding = 'VALID', scope = 'MaxPool_la_3x3')
# 320 + 192 + 768 = 1280
net = tf.concat([branch_0, branch_1, branch_2], 3)
'''
第三個Inception模塊組:第二個Module
input:8x8x1280
output:8x8x2048
'''
with tf.variable_scope('Mixed_7b'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 320, [1, 1], scope = 'Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 384, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = tf.concat([
slim.conv2d(branch_1, 384, [1, 3], scope = 'Conv2d_0b_1x3'),
slim.conv2d(branch_1, 384, [3, 1], scope = 'Conv2d_0b_3x1')], 3)
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 448, [1, 1], scope = 'Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, 384, [3, 3], scope = 'Conv2d_0b_3x3')
branch_2 = tf.concat([
slim.conv2d(branch_2, 384, [1, 3], scope = 'Conv2d_0c_1x3'),
slim.conv2d(branch_2, 384, [3, 1], scope = 'Conv2d_0c_3x1')], 3)
with tf.variable_scope('Branch_3'):
branch_3 = slim.avg_pool2d(net, [3, 3], scope = 'AvgPool_0a_3x3')
branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope = 'Conv2d_0b_1x1')
# 320 + 384*2 + 384*2 + 192 = 2048
tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
'''
第三個Inception模塊組:第三個Module(與第二個完全一樣)
input:8x8x2048
output:8x8x2048
'''
with tf.variable_scope('Mixed_7c'):
with tf.variable_scope('Branch_0'):
branch_0 = slim.conv2d(net, 320, [1, 1], scope = 'Conv2d_0a_1x1')
with tf.variable_scope('Branch_1'):
branch_1 = slim.conv2d(net, 384, [1, 1], scope = 'Conv2d_0a_1x1')
branch_1 = tf.concat([
slim.conv2d(branch_1, 384, [1, 3], scope = 'Conv2d_0b_1x3'),
slim.conv2d(branch_1, 384, [3, 1], scope = 'Conv2d_0b_3x1')], 3)
with tf.variable_scope('Branch_2'):
branch_2 = slim.conv2d(net, 448, [1, 1], scope = 'Conv2d_0a_1x1')
branch_2 = slim.conv2d(branch_2, 384, [3, 3], scope = 'Conv2d_0b_3x3')
branch_2 = tf.concat([
slim.conv2d(branch_2, 384, [1, 3], scope = 'Conv2d_0c_1x3'),
slim.conv2d(branch_2, 384, [3, 1], scope = 'Conv2d_0c_3x1')], 3)
with tf.variable_scope('Branch_3'):
branch_3 = slim.avg_pool2d(net, [3, 3], scope = 'AvgPool_0a_3x3')
branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope = 'Conv2d_0b_1x1')
# 320 + 384*2 + 384*2 + 192 = 2048
tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
return net, end_points
定義Inception V3網絡的最後一部分:
# Inception V3網絡的最後一部分
def incepiton_v3(inputs,
num_class = 1000,
is_training = True,
dropout_keep_prob = 0.8,
prediction_fn = slim.softmax,
spatial_squeeze = True,
reuse = None,
scope = 'InceptionV3'):
'''
inputs: 輸入
num_class: 最後需要分類的總數
is_training: 標誌是否是訓練過程,對BN和Dropout有影響
dropout_keep_prob: 保留節點的比例
prediction_fn: 用來分類的函數
spatial_squeeze: 是否要將型如5x3x1--->5x3
reuse: 標誌是否會對網絡和Variable進行重複使用
scope: 包含函數默認參數的環境
'''
with tf.variable_scope(scope, 'InceptionV3', [inputs, num_class], reuse = reuse) as scope:
# 使用slim.arg_scope進行默認初始化設置
with slim.arg_scope([slim.batch_norm, slim.dropout], is_training = is_training):
net, end_points = inception_v3_base(inputs, scope = scope)
with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d], stride = 1, padding = 'SAME'):
aux_logits = end_points['Mixed_6e'] # 輔助分類結點
with tf.variable_scope('AuxLogits'):
# 進行池化
aux_logits = slim.avg_pool2d(aux_logits, [5, 5], stride = 3, padding = 'VALID', scope = 'AvgPool_1a_5x5')
# 進行卷積
aux_logits = slim.conv2d(aux_logits, 128, [1, 1], scope = 'Conv2d_1b_1x1')
aux_logits = slim.conv2d(aux_logits, 768, [5, 5],
weights_initializer = trunc_normal(0.01),
padding = 'VALID', scope = 'Conv2d_2a_5x5')
aux_logits = slim.conv2d(aux_logits, num_class, [1, 1],
activation_fn = None,
weights_initializer = trunc_normal(0.001),
scope = 'Conv2d_2b_1x1')
if spatial_squeeze:
# [1, 2]表示把第2,3維出現的1去掉(前提得2,3本就存在1)
aux_logits = tf.squeeze(aux_logits, [1, 2], name = 'SpatialSqueeze')
end_points['AuxLogits'] = aux_logits
with tf.variable_scope('Logits'):
# 直接對Mixed_7e即最後一個卷積層的輸出進行操作
net = slim.avg_pool2d(net, [8, 8], padding = 'VALID', scope = 'AvgPool_1a_8x8')
net = slim.dropout(net, keep_prob = dropout_keep_prob, scope = 'Dropout_1b')
end_points['PreLogits'] = net
logits = slim.conv2d(net, num_class, [1, 1], activation_fn = None,
normalizer_fn = None, scope = 'Conv2d_1c_1x1')
if spatial_squeeze:
logits = tf.squeeze(logits, [1, 2], name = 'SpatialSqueeze')
end_points['Logits'] = logits
# 使用softmax函數預測
end_points['Predictions'] = prediction_fn(logits, scope = 'Predictions')
return logits, end_points
定義耗時:
# 計算耗時
def time_tensorflow_run(session, target, info_string):
num_steps_burn_in = 10 # 打印閾值
total_duration = 0.0 # 每一輪所需要的迭代時間
total_duration_aquared = 0.0 # 每一輪所需要的迭代時間的平方
for i in range(num_batches + num_steps_burn_in):
start_time = time.time()
_ = session.run(target)
duration = time.time() - start_time # 計算耗時
if i >= num_steps_burn_in:
if not i % 10:
print("%s : step %d, duration = %.3f" % (datetime.now(), i - num_steps_burn_in, duration))
total_duration += duration
total_duration_aquared += duration * duration
mn = total_duration / num_batches # 計算均值
vr = total_duration_aquared / num_batches - mn * mn # 計算方差
sd = math.sqrt(vr) # 計算標準差
print("%s : %s across %d steps, %.3f +/- %.3f sec/batch" % (datetime.now(), info_string, num_batches, mn, sd))
測試:
注:CNN的訓練都是比較耗時的,所以這裏也就是測試一下幾張隨機生成圖的前向和反向傳播過程
batch_size = 32
height, width = 299, 299
inputs = tf.random_uniform((batch_size, height, width, 3))
# 加載前面定義好的inception_v3_arg_scope()
with slim.arg_scope(inception_v3_arg_scope()):
logits, end_points = incepiton_v3(inputs, is_training = False)
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
num_batches = 100
time_tensorflow_run(sess, logits, "Forward")
運行效果:
2019-01-22 13:02:51.088969 : step 0, duration = 0.231
2019-01-22 13:02:53.406683 : step 10, duration = 0.231
2019-01-22 13:02:55.725737 : step 20, duration = 0.233
2019-01-22 13:02:58.050072 : step 30, duration = 0.231
2019-01-22 13:03:00.372407 : step 40, duration = 0.233
2019-01-22 13:03:02.694779 : step 50, duration = 0.234
2019-01-22 13:03:05.019621 : step 60, duration = 0.232
2019-01-22 13:03:07.343221 : step 70, duration = 0.234
2019-01-22 13:03:09.665730 : step 80, duration = 0.232
2019-01-22 13:03:11.990585 : step 90, duration = 0.233
2019-01-22 13:03:14.090070 : Forward across 100 steps, 0.232 +/- 0.001 sec/batch
[1] Szegedy C, Vanhoucke V, Ioffe S, et al. Rethinking the inception architecture for computer vision[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2016: 2818-2826.
[2] Tensorflo實戰.黃文堅,唐源
如果覺得我有地方講的不好的或者有錯誤的歡迎給我留言,謝謝大家閱讀(點個讚我可是會很開心的哦)~