├── images └── architecture.png ├── .idea ├── vcs.xml ├── modules.xml ├── SqueezeNet-tf.iml └── misc.xml ├── README.md ├── LICENSE └── SqueezeNet.py /images/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dawars/SqueezeNet-tf/HEAD/images/architecture.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/SqueezeNet-tf.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SqueezeNet-tf 2 | A Tensorflow SqueezeNet implementation of the research https://arxiv.org/abs/1602.07360 3 | 4 | ## What is SqueezeNet? 5 | SqueezeNet is a convolutional neural network with 80.3% top-5 accuracy on the ImageNet dataset. 6 | This architecture aims to signifanctly reduce the size of the model. 7 | 8 | ## Goals 9 | - [x] Building the network 10 | - [ ] Training the network on imagenet 11 | * Currently published pre-trained weights cannot be used in TensorFlow, the goal of this project is to produce easy-to-use save files. 12 | - [ ] Neural Style Transfer (http://arxiv.org/abs/1508.06576) on mobile devices 13 | * Running on mobile devices in reasonable time without sacraficing quality too much like other feed-forward approaches. 14 | 15 | ![Architecture](images/architecture.png?raw=true "Architecture") 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dávid Komorowicz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SqueezeNet.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | import cv2 4 | 5 | 6 | class SqueezeNet(object): 7 | def __init__(self, session, alpha, optimizer=tf.train.GradientDescentOptimizer, squeeze_ratio=1): 8 | if session: 9 | self.session = session 10 | else: 11 | self.session = tf.Session() 12 | 13 | self.dropout = tf.placeholder(tf.float32) 14 | self.target = tf.placeholder(tf.float32, [None, 1000]) 15 | self.imgs = tf.placeholder(tf.float32, [None, 224, 224, 3]) 16 | 17 | self.alpha = alpha 18 | self.sq_ratio = squeeze_ratio 19 | self.optimizer = optimizer 20 | 21 | self.weights = {} 22 | self.net = {} 23 | 24 | self.build_model() 25 | self.init_opt() 26 | self.init_model() 27 | 28 | def build_model(self): 29 | net = {} 30 | 31 | # Caffe order is BGR, this model is RGB. 32 | # The mean values are from caffe protofile from DeepScale/SqueezeNet github repo. 33 | self.mean = tf.constant([123.0, 117.0, 104.0], 34 | dtype=tf.float32, shape=[1, 1, 1, 3], name='img_mean') 35 | images = self.imgs-self.mean 36 | 37 | net['input'] = images 38 | 39 | # conv1_1 40 | net['conv1'] = self.conv_layer('conv1', net['input'], 41 | W=self.weight_variable([3, 3, 3, 64], name='conv1_w'), stride=[1, 2, 2, 1]) 42 | 43 | net['relu1'] = self.relu_layer('relu1', net['conv1'], b=self.bias_variable([64], 'relu1_b')) 44 | net['pool1'] = self.pool_layer('pool1', net['relu1']) 45 | 46 | net['fire2'] = self.fire_module('fire2', net['pool1'], self.sq_ratio * 16, 64, 64) 47 | net['fire3'] = self.fire_module('fire3', net['fire2'], self.sq_ratio * 16, 64, 64, True) 48 | net['pool3'] = self.pool_layer('pool3', net['fire3']) 49 | 50 | net['fire4'] = self.fire_module('fire4', net['pool3'], self.sq_ratio * 32, 128, 128) 51 | net['fire5'] = self.fire_module('fire5', net['fire4'], self.sq_ratio * 32, 128, 128, True) 52 | net['pool5'] = self.pool_layer('pool5', net['fire5']) 53 | 54 | net['fire6'] = self.fire_module('fire6', net['pool5'], self.sq_ratio * 48, 192, 192) 55 | net['fire7'] = self.fire_module('fire7', net['fire6'], self.sq_ratio * 48, 192, 192, True) 56 | net['fire8'] = self.fire_module('fire8', net['fire7'], self.sq_ratio * 64, 256, 256) 57 | net['fire9'] = self.fire_module('fire9', net['fire8'], self.sq_ratio * 64, 256, 256, True) 58 | 59 | # 50% dropout 60 | net['dropout9'] = tf.nn.dropout(net['fire9'], self.dropout) 61 | net['conv10'] = self.conv_layer('conv10', net['dropout9'], 62 | W=self.weight_variable([1, 1, 512, 1000], name='conv10', init='normal')) 63 | net['relu10'] = self.relu_layer('relu10', net['conv10'], b=self.bias_variable([1000], 'relu10_b')) 64 | net['pool10'] = self.pool_layer('pool10', net['relu10'], pooling_type='avg') 65 | 66 | avg_pool_shape = tf.shape(net['pool10']) 67 | net['pool_reshaped'] = tf.reshape(net['pool10'], [avg_pool_shape[0],-1]) 68 | self.fc2 = net['pool_reshaped'] 69 | self.logits = net['pool_reshaped'] 70 | 71 | self.probs = tf.nn.softmax(self.logits) 72 | self.net = net 73 | 74 | def init_opt(self): 75 | self.cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.logits, labels=self.target)) 76 | self.optimize = self.optimizer(self.alpha).minimize(self.cost) 77 | 78 | def init_model(self): 79 | init_op = tf.global_variables_initializer() 80 | self.session.run(init_op) 81 | 82 | def bias_variable(self, shape, name, value=0.1): 83 | initial = tf.constant(value, shape=shape) 84 | self.weights[name] = tf.Variable(initial) 85 | return self.weights[name] 86 | 87 | def weight_variable(self, shape, name=None, init='xavier'): 88 | if init == 'variance': 89 | initial = tf.get_variable('W' + name, shape, initializer=tf.contrib.layers.variance_scaling_initializer()) 90 | elif init == 'xavier': 91 | initial = tf.get_variable('W' + name, shape, initializer=tf.contrib.layers.xavier_initializer()) 92 | else: 93 | initial = tf.Variable(tf.random_normal(shape, stddev=0.01), name='W'+name) 94 | 95 | self.weights[name] = initial 96 | return self.weights[name] 97 | 98 | def relu_layer(self, layer_name, layer_input, b=None): 99 | if b: 100 | layer_input += b 101 | relu = tf.nn.relu(layer_input) 102 | return relu 103 | 104 | def pool_layer(self, layer_name, layer_input, pooling_type='max'): 105 | if pooling_type == 'avg': 106 | pool = tf.nn.avg_pool(layer_input, ksize=[1, 13, 13, 1], 107 | strides=[1, 1, 1, 1], padding='VALID') 108 | elif pooling_type == 'max': 109 | pool = tf.nn.max_pool(layer_input, ksize=[1, 3, 3, 1], 110 | strides=[1, 2, 2, 1], padding='VALID') 111 | return pool 112 | 113 | def conv_layer(self, layer_name, layer_input, W, stride=[1, 1, 1, 1]): 114 | return tf.nn.conv2d(layer_input, W, strides=stride, padding='SAME') 115 | 116 | def fire_module(self, layer_name, layer_input, s1x1, e1x1, e3x3, residual=False): 117 | """ Fire module consists of squeeze and expand convolutional layers. """ 118 | fire = {} 119 | 120 | shape = layer_input.get_shape() 121 | 122 | # squeeze 123 | s1_weight = self.weight_variable([1, 1, int(shape[3]), s1x1], layer_name + '_s1') 124 | 125 | # expand 126 | e1_weight = self.weight_variable([1, 1, s1x1, e1x1], layer_name + '_e1') 127 | e3_weight = self.weight_variable([3, 3, s1x1, e3x3], layer_name + '_e3') 128 | 129 | fire['s1'] = self.conv_layer(layer_name + '_s1', layer_input, W=s1_weight) 130 | fire['relu1'] = self.relu_layer(layer_name + '_relu1', fire['s1'], 131 | b=self.bias_variable([s1x1], layer_name + '_fire_bias_s1')) 132 | 133 | fire['e1'] = self.conv_layer(layer_name + '_e1', fire['relu1'], W=e1_weight) 134 | fire['e3'] = self.conv_layer(layer_name + '_e3', fire['relu1'], W=e3_weight) 135 | fire['concat'] = tf.concat([tf.add(fire['e1'], self.bias_variable([e1x1], 136 | name=layer_name + '_fire_bias_e1' )), 137 | tf.add(fire['e3'], self.bias_variable([e3x3], 138 | name=layer_name + '_fire_bias_e3' ))], 3) 139 | 140 | if residual: 141 | fire['relu2'] = self.relu_layer(layer_name + 'relu2_res', tf.add(fire['concat'],layer_input)) 142 | else: 143 | fire['relu2'] = self.relu_layer(layer_name + '_relu2', fire['concat']) 144 | 145 | return fire['relu2'] 146 | 147 | def save_model(self, path): 148 | """ 149 | Save the neural network model. 150 | :param path: path where will be stored 151 | :return: path if success 152 | """ 153 | saver = tf.train.Saver(self.weights) 154 | save_path = saver.save(self.session, path) 155 | return save_path 156 | 157 | def load_model(self, path): 158 | """ 159 | Load neural network model from path. 160 | :param path: path where is network located. 161 | :return: None 162 | """ 163 | saver = tf.train.Saver(self.weights) 164 | saver.restore(self.session, path) 165 | 166 | if __name__ == '__main__': 167 | sess = tf.Session() 168 | alpha= tf.placeholder(tf.float32) 169 | net = SqueezeNet(sess, alpha) 170 | 171 | img1 = cv2.imread('./images/architecture.png')#, mode='RGB') 172 | img1 = cv2.cvtColor(img1,cv2.COLOR_BGR2RGB) 173 | img1 = cv2.resize(img1, (224, 224)) 174 | prob = sess.run(net.probs, feed_dict={net.net['input']: [img1], net.dropout:1.0}) 175 | print(prob) 176 | net.save_model('./test.ckpt') 177 | net.load_model('./test.ckpt') 178 | --------------------------------------------------------------------------------