1. 简介
主要实现LLNet模型的神经网络结构
2. 模型实现
# Ref: LLNet: Deep Autoencoders for Low-light Image Enhancement # # CVPR 2014 # # Author: HSW # Date: 2018-05-11 import tensorflow as tf import numpy as np class LLNet_Model(object): def __init__(self, LLNet_Shape=(289, 847, 578, 289), sparseCoef = 0.05, beta_pretrain, lambda_pretrain, lambda_finetune, transfer_function=tf.nn.softplus): ''' LLNet Model Inputs is 17 x 17 image Patch: 289 pixels ''' # Inputs + Outputs self.inputs = tf.placeholder(tf.float32, [None, self.LLnet_Shape[0]]) self.labels = tf.placeholder(tf.float32, [None, self.LLNet_Shape[0]]) # other initial Params self.LLnet_Shape = LLNet_Shape self.transfer = transfer_function self.sparseCoef = sparseCoef self.beta_pretrain = beta_pretrain self.lambda_pretrain = lambda_pretrain self.lambda_finetune = lambda_finetune self.weights = self.initial_weights() def initial_weights(self): ''' Create LLNet weights and biads ''' all_weights = dict() # Layer1 all_weights['w1'] = tf.Variable(xavier_init(self.LLnet_Shape[0], self.LLnet_Shape[1])) all_weights['b1'] = tf.Variable(tf.zeros([self.LLnet_Shape[1]], dtype=tf.float32)) # Layer2 all_weigths['w2'] = tf.Variable(xavier_init(self.LLnet_Shape[1], self.LLnet_Shape[2])) all_weights['b2'] = tf.Variable(tf.zeros([self.LLnet_Shape[2]], dtype=tf.float32)) # Layer3 all_weights['w3'] = tf.Variable(xavier_init(self.LLnet_Shape[2], self.LLnet_Shape[3])) all_weights['b3'] = tf.Variable(tf.zeros([self.LLnet_Shape[3]], dtype=tf.float32)) # Layer4 all_weights['w4'] = tf.Variable(xavier_init(self.LLnet_Shape[3], self.LLnet_Shape[2])) all_weights['b4'] = tf.Variable(tf.zeros([self.LLnet_Shape[2]], dtype=tf.float32)) # Layer5 all_weights['w5'] = tf.Variable(xavier_init(self.LLnet_Shape[2], self.LLnet_Shape[1])) all_weights['b5'] = tf.Variable(tf.zeros([self.LLnet_Shape[1]], dtype=tf.float32)) # Layer6 all_weights['w6'] = tf.Variable(xavier_init(self.LLnet_Shape[1], self.LLnet_Shape[0])) all_weights['b6'] = tf.Variable(tf.zeros([self.LLnet_Shape[0]], dtype=tf.float32)) return all_weights def build_graph_pretrain(self): '''Create LLNet Graph ''' self.inputs = tf.placeholder(tf.float32, [None, self.LLnet_Shape[0]]) self.labels = tf.placeholder(tf.float32, [None, self.LLNet_Shape[0]]) self.hidder1 = self.transfer(tf.add(tf.matmul(self.inputs, self.weights['w1']), self.weights['b1'])) self.hidder2 = self.transfer(tf.add(tf.matmul(self.hidder1, self.weights['w2']), self.weights['b2'])) self.hidder3 = self.transfer(tf.add(tf.matmul(self.hidder2, self.weights['w3']), self.weights['b3'])) self.hidder4 = self.transfer(tf.add(tf.matmul(self.hidder3, self.weight['w4']), self.weights['b4'])) self.hidder5 = self.transfer(tf.add(tf.matmul(self.hidder4, self.weight['w5']), self.weights['b5'])) self.ouputs = self.transfer(self.add(tf.matmul(self.hidder5, self.weight['w6']), self.weights['b6'])) # First Two Layer self.var1 = tf.trainable_variables()[0:4] # Last Layer self.var2 = tf.trainable_variables()[4:] loss_pretrain() optimizer_pretrain() init = tf.global_variables_initializer() self.sess = tf.Session() self.sess.run(init) def build_graph_finetune(self, epoch): '''Create LLNet Graph ''' self.hidder1 = self.transfer(tf.add(tf.matmul(self.inputs, self.weights['w1']), self.weights['b1'])) self.hidder2 = self.transfer(tf.add(tf.matmul(self.hidder1, self.weights['w2']), self.weights['b2'])) self.hidder3 = self.transfer(tf.add(tf.matmul(self.hidder2, self.weights['w3']), self.weights['b3'])) self.hidder4 = self.transfer(tf.add(tf.matmul(self.hidder3, self.weights['w4']), self.weights['b4'])) self.hidder5 = self.transfer(tf.add(tf.matmul(self.hidder4, self.weights['w5']), self.weights['b5'])) self.ouputs = self.transfer(tf.add(tf.matmul(self.hidder5, self.weights['w6']), self.weights['b6'])) loss_finetune() optimizer_finetune_first() optimizer_finetune_last() self.saver = tf.train.Saver() init = tf.global_variables_initializer() self.sess = tf.Session() self.sess.run(init) def loss_pretrain(self): ''' Compute LLNet Graph loss in pre-train''' self.data_loss_pretrain = tf.reduce_mean(tf.pow(tf.subtract(self.outputs, self.labels), 2)) sparse_hidder1 = tf.reduce_mean(self.hidder1, 0) KL_hidder1 = sparse_hidder1 * tf.log(sparse_hidder1 / self.sparseCoef) + (1 - self.sparseCoef) * tf.log((1 - self.sparseCoef) / (1 - sparse_hidder1)) sparse_hidder2 = tf.reduce_mean(self.hidder2, 0) KL_hidder2 = sparse_hidder2 * tf.log(sparse_hidder2 / self.sparseCoef) + (1 - self.sparseCoef) * tf.log((1 - self.sparseCoef) / (1 - sparse_hidder2)) sparse_hidder3 = tf.reduce_mean(self.hidder3, 0) KL_hidder3 = sparse_hidder3 * tf.log(sparse_hidder2 / self.sparseCoef) + (1 - self.sparseCoef) * tf.log((1 - self.sparseCoef) / (1 - sparse_hidder3)) sparse_hidder4 = tf.reduce_mean(self.hidder4, 0) KL_hidder4 = sparse_hidder4 * tf.log(sparse_hidder2 / self.sparseCoef) + (1 - self.sparseCoef) * tf.log((1 - self.sparseCoef) / (1 - sparse_hidder4)) sparse_hidder5 = tf.reduce_mean(self.hidder5, 0) KL_hidder5 = sparse_hidder5 * tf.log(sparse_hidder2 / self.sparseCoef) + (1 - self.sparseCoef) * tf.log((1 - self.sparseCoef) / (1 - sparse_hidder5)) self.kl_loss_pretrain = sparse_hidder1 + sparse_hidder2 + sparse_hidder3 + sparse_hidder4 + sparse_hidder5 norm_w1 = tf.norm(self.weights['w1'], ord='fro', axis=[-2, -1]) norm_w2 = tf.norm(self.weights['w2'], ord='fro', axis=[-2, -1]) norm_w3 = tf.norm(self.weights['w3'], ord='fro', axis=[-2, -1]) norm_w4 = tf.norm(tf.tranpose(self.weights['w3']), ord='fro', axis=[-2,-1]) norm_w5 = tf.norm(tf.tranpose(self.weights['w2']), ord='fro', axis=[-2,-1]) norm_w6 = tf.norm(tf.tranpose(self.weights['w1']), ord='fro', axis=[-2,-1]) self.sparse_loss_pretrain = norm_w1 + norm_w2 + norm_w3 + norm_w4 + norm_w5 + norm_w6 # 总损失函数 self.pretrain_loss = self.data_loss_pretrain + self.beta_pretrain * self.kl_loss_pretrain + self.lambda_pretrain * self.sparse_loss_pretrain def loss_finetune(self, lambda_finetune): ''' Compute LLNet Graph loss in finetuned ''' # data loss self.data_loss_finetune = tf.reduce_mean(tf.pow(tf.subtract(self.outputs, self.labels), 2)) norm_w1 = tf.norm(self.weights['w1'], ord='fro', axis=[-2, -1]) norm_w2 = tf.norm(self.weights['w2'], ord='fro', axis=[-2, -1]) norm_w3 = tf.norm(self.weights['w3'], ord='fro', axis=[-2, -1]) norm_w4 = tf.norm(tf.tranpose(self.weights['w3']), ord='fro', axis=[-2,-1]) norm_w5 = tf.norm(tf.tranpose(self.weights['w2']), ord='fro', axis=[-2,-1]) norm_w6 = tf.norm(tf.tranpose(self.weights['w1']), ord='fro', axis=[-2,-1]) # sparse loss self.sparse_loss_finetune = norm_w1 + norm_w2 + norm_w3 + norm_w4 + norm_w5 + norm_w6 # total loss self.finetune_loss = self.data_loss_finetune + self.lambda_finetune * self.sparse_loss_finetune def optimizer_pretrain(self, lr_first = 0.1, lr_last = 0.01): ''' Compute LLNet optimizer in pre-train ''' opt_first = tf.AdamOptimizer(lr_first).minimizer(self.pretrain_loss, var_list=self.var1) opt_last = tf.AdamOptimizer(lr_last).minimizer(self.pretrain_loss, var_list=self.var2) self.pretrain_opt = tf.group(opt_first, opt_last) def optimizer_finetune_first(self, lr_first = 0.1): ''' Compute LLNet optimizer in finetune ''' self.finetune_opt_first = tf.AdamOptimizer(lr_first).minimizer(self.finetune_loss) def optimizer_finetune_last(self, lr_last = 0.01): ''' Compute LLNet optimizer in finetune ''' self.finetune_opt_last = tf.AdamOptimizer(lr_first).minimizer(self.finetune_loss) def xavier_init(self, fan_in, fan_out, constant = 1): ''' Data initial ''' low = -constant * np.sqrt(6.0 / (fan_in + fan_out)) high = constant * np.sqrt(6.0 / (fan_in + fan_out)) return tf.random_uniform((fan_in, fan_out), minval=low, maxval=high, dtype=tf.float32) def run_fitting_pretrain(self, inputs, labels): ''' run pre-train ''' return self.sess.run((self.pretrain_loss, self.pretrain_opt), feed_dict={self.Inputs: inputs, self.labels: labels}) def run_fitting_finetune_first(self, inputs, labels): ''' run finetune at first stage ''' return self.sess.run((self.finetune_loss, self.finetune_opt_first), feed_dict={self.Inputs: inputs, self.labels: labels}) def run_fitting_finetune_last(self, inputs, labels): ''' run finetune at second stage ''' return self.sess.run((self.finetune_loss, self.finetune_opt_last), feed_dict={self.Inputs: inputs, self.labels: labels})
实际在实现的过程中,存在一个疑问,就是在预训练和调优过程中,使用不同的学习率,本人的实现方式是否合适呢?