├── .gitignore ├── README.md ├── densenet.py ├── train.py └── utils.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DenseNet_Tensorflow 2 | Tensorflow implementation of denseness 3 | 4 | 更多关于DenseNet可参考[博文](https://www.jianshu.com/p/64382ae8ca1b) 5 | -------------------------------------------------------------------------------- /densenet.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | 4 | class Model(object): 5 | 6 | def __init__(self, FLAGS): 7 | self.image_width = FLAGS.image_width 8 | self.image_height = FLAGS.image_height 9 | self.num_image_channels = FLAGS.num_image_channels 10 | self.batch_size = FLAGS.batch_size 11 | self.num_epochs = FLAGS.num_epochs 12 | self.num_classes = FLAGS.num_classes 13 | self.growth_rate = FLAGS.growth_rate 14 | self.num_layers_in_dense_block = int(FLAGS.num_layers - 4 / 3) if int(FLAGS.num_layers - 4 / 3) > 0 else 12 15 | self.learning_rate = FLAGS.learning_rate 16 | self.dropout_prob = FLAGS.dropout_prob 17 | self.compression = FLAGS.compression 18 | self.inputs = tf.placeholder(dtype=tf.float32, shape=[self.batch_size, self.image_width * self.image_height * self.num_image_channels], name='inputs') 19 | self.labels = tf.placeholder(dtype=tf.float32, shape=[self.batch_size, self.num_classes]) 20 | self.correct_predictions, self.loss, self.accuracy, self.optimizer = self.net() 21 | 22 | def conv_layer(self, x): 23 | return tf.layers.conv2d(inputs=x, filters=16, kernel_size=3, strides=1, padding='same', kernel_initializer=tf.random_normal_initializer(stddev=0.01)) 24 | 25 | def dense_block(self, p): 26 | for i in range(self.num_layers_in_dense_block): 27 | with tf.variable_scope('bottle_neck{0}'.format(i)): 28 | x = tf.layers.batch_normalization(p) 29 | x = tf.nn.relu(x) 30 | x = tf.layers.conv2d(inputs=x, filters=self.growth_rate, kernel_size=3, strides=1, padding='same', kernel_initializer=tf.random_normal_initializer(stddev=0.01)) 31 | x = tf.concat([x, p], axis=3) 32 | p = x 33 | return x 34 | 35 | def transition_layer(self, x): 36 | x = tf.layers.batch_normalization(x) 37 | x = tf.nn.relu(x) 38 | n_inchannels = x.get_shape().as_list()[3] 39 | n_outchannels = int(n_inchannels * self.compression) 40 | x = tf.layers.conv2d(inputs=x, filters=n_outchannels, kernel_size=1, strides=1, padding='same', kernel_initializer=tf.random_normal_initializer(stddev=0.01)) 41 | x = tf.layers.average_pooling2d(inputs=x, pool_size=2, strides=2) 42 | return x 43 | 44 | def net(self): 45 | x = tf.reshape(self.inputs, shape=[-1, self.image_width, self.image_height, self.num_image_channels]) 46 | c = self.conv_layer(x) 47 | with tf.variable_scope('dense_block1') as scope: 48 | b1 = self.dense_block(c) 49 | 50 | with tf.variable_scope('transition1') as scope: 51 | t1 = self.transition_layer(b1) 52 | 53 | with tf.variable_scope('dense_block2') as scope: 54 | b2 = self.dense_block(t1) 55 | 56 | with tf.variable_scope('transition2') as scope: 57 | t2 = self.transition_layer(b2) 58 | 59 | with tf.variable_scope('dense_block3') as scope: 60 | b3 = self.dense_block(t2) 61 | 62 | b = tf.layers.batch_normalization(b3) 63 | r = tf.nn.relu(b) 64 | g = tf.layers.average_pooling2d(r, pool_size=[b3.get_shape().as_list()[1], b3.get_shape().as_list()[2]], strides=1) 65 | g = tf.squeeze(g) 66 | logits = tf.layers.dense(g, self.num_classes, activation='linear') 67 | loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=self.labels, logits=logits)) 68 | correct_predictions = tf.reduce_sum(tf.cast(tf.equal(tf.argmax(self.labels, axis=1), tf.argmax(logits, axis=1)), tf.float32)) 69 | accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(self.labels, axis=1), tf.argmax(logits, axis=1)), tf.float32)) 70 | optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate).minimize(loss) 71 | return correct_predictions, loss, accuracy, optimizer 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from densenet import Model 3 | from utils import DataProcessor 4 | 5 | tf.flags.DEFINE_integer('batch_size', 32, 'batch size') 6 | tf.flags.DEFINE_integer('num_epochs', 20, 'number of epochs') 7 | tf.flags.DEFINE_integer('densenet_length', 40, 'lenght of densenet') 8 | tf.flags.DEFINE_integer('image_width', 32, 'the width of the image') 9 | tf.flags.DEFINE_integer('image_height', 32, 'the height of the image') 10 | tf.flags.DEFINE_integer('num_image_channels', 3, 'number of channels of the image') 11 | tf.flags.DEFINE_integer('num_classes', 10, 'number of classes') 12 | tf.flags.DEFINE_integer('growth_rate', 12, 'growth rate') 13 | tf.flags.DEFINE_integer('num_layers', 40, 'number of layers in densenet') 14 | tf.flags.DEFINE_float('learning_rate', 1.0e-3, 'learning rate') 15 | tf.flags.DEFINE_float('dropout_prob', 0.5, 'dropout probability') 16 | tf.flags.DEFINE_float('compression', 0.5, 'compression ratio') 17 | tf.flags.DEFINE_string('train_path', 'cifar-10-batches-py/data_batch_1', 'training data path') 18 | tf.flags.DEFINE_string('test_path', 'cifar-10-batches-py/test_batch', 'test data path') 19 | FLAGS = tf.flags.FLAGS 20 | 21 | 22 | data_processor = DataProcessor(FLAGS) 23 | data = data_processor.load_data(FLAGS.train_path) 24 | test_data = data_processor.load_data(FLAGS.test_path) 25 | model = Model(FLAGS) 26 | 27 | 28 | def evaluate(): 29 | total_correct_predictions = 0 30 | num_test_samples = len(test_data[b'labels']) 31 | for inputs, labels in data_processor.data_generator(test_data): 32 | batch_correct_predictions = sess.run(model.correct_predictions, feed_dict={model.inputs: inputs, model.labels: labels}) 33 | total_correct_predictions += batch_correct_predictions 34 | test_accuracy = 1.0 * total_correct_predictions / num_test_samples 35 | return test_accuracy 36 | 37 | 38 | with tf.Session() as sess: 39 | sess.run(tf.global_variables_initializer()) 40 | i = 0 41 | for inputs, labels in data_processor.data_generator(data): 42 | feed_dict = { 43 | model.inputs: inputs, 44 | model.labels: labels, 45 | } 46 | _, loss, accuracy = sess.run([model.optimizer, model.loss, model.accuracy], feed_dict=feed_dict) 47 | print(loss, accuracy) 48 | i += 1 49 | if i % 100 == 0: 50 | test_accuracy = evaluate() 51 | print(test_accuracy) 52 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import numpy as np 3 | 4 | 5 | class DataProcessor(object): 6 | 7 | def __init__(self, FLAGS): 8 | self.batch_size = FLAGS.batch_size 9 | self.num_epochs = FLAGS.num_epochs 10 | self.num_classes = FLAGS.num_classes 11 | 12 | def load_data(self, fname): 13 | with open(fname, 'rb') as f: 14 | data = pickle.load(f, encoding='bytes') 15 | return data 16 | 17 | def data_generator(self, data): 18 | num_batches = int(len(data[b'labels']) / self.batch_size) 19 | for epoch_id in range(self.num_epochs): 20 | for batch_id in range(num_batches): 21 | inputs = data[b'data'][batch_id * self.batch_size: (batch_id + 1) * self.batch_size] 22 | labels = data[b'labels'][batch_id * self.batch_size: (batch_id + 1) * self.batch_size] 23 | labels = np.eye(self.num_classes)[labels] 24 | yield inputs, labels 25 | --------------------------------------------------------------------------------