deep_dream:
tensorflow_inception_graph.pb 下载地址:https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
#-*-coding:utf-8-*-
import tensorflow as tf
import numpy as np
import scipy.misc
graph = tf.Graph()
sess = tf.InteractiveSession(graph=graph)
##data_preprocess
t_input = tf.placeholder(np.float32, name='input')
imagenet_mean = 117.0
t_preprocessed = tf.expand_dims(t_input - imagenet_mean, 0)
## load the model
model = 'tensorflow_inception_graph.pb'
with tf.gfile.FastGFile(model, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
tf.import_graph_def(graph_def,{'input':t_preprocessed})
##test :print out options in grapg
# layers = [op.name for op in graph.get_operations() if op.type=='Conv2D' and 'import/' in op.name]
# print(len(layers))
# for item in layers:
# print(item)
# item = 'import/mixed5b_pool_reduce_pre_relu/conv:0'
# print('shape of %s:%s'%(item,str(graph.get_tensor_by_name(item).get_shape())))
##save array as image
def savearray(img_array,img_name):
scipy.misc.toimage(img_array).save(img_name)
print('img save as:%s'%(img_name))
##generate dream image
def deep_dream(feature_map,img_input,iter_n=20,learning_rate=1):
score = tf.reduce_mean(feature_map)
gradient = tf.gradients(score,t_input)[0]
img_out = img_input.copy()
for i in range(iter_n):
g,s = sess.run([gradient,score],feed_dict={t_input:img_out})
g_std = g.std()
g = g/(g_std+1e-8)
img_out = img_out + g*learning_rate
print('step = %03d,score = %f'%(i,s))
savearray(img_out, 'my_deep_dream.jpg')
##main
def main(_):
layer_name = 'mixed5b_pool_reduce_pre_relu'
tensor_feature = graph.get_tensor_by_name('import/%s/conv:0'%(layer_name))
channel = 100
feature_map = tensor_feature[:,:,:,channel]
img_input = np.random.uniform(size=(256,256,3))+100
deep_dream(feature_map,img_input)
if __name__=='__main__':
tf.app.run()
结果图:
deep_dream 原理分析:
我们从神经网络中学到了什么?
1)神经网络在训练结束后,保存的模型只包含网络结构与加权、偏置等参数,每个layer中的tensor只保留了对应的shape(更严格说只有tensor的维数和通道数两个参数),而没有实际内容,tensor的具体内容需要有具体的输入数据后才产生。
2)神经网络中的某个layer得到的tensor中的某个channel的feature_map对最后的输出有多大贡献,与该feature_map的均值成正相关,如果该feature_map的均值越大,其卷积后或展平后,在加权输出的时候,所占的比例就越大,对最终结果的影响就越大。所以,我们可以设计网络,让输入成为自变量,网络参数是固定值,某feature_map的均值是因变量,看看是怎样的输入使得该feature_map的均值最大,间接地反映该feature_map对什么输入最敏感,即该feature_map提取了什么特征。
deep_dream就是采用第二种方式查看feature_map学习到了什么特征(或对什么特征敏感/有感觉)
deep_dream的feature_map均值最大化原理:梯度上升法,用均值对输入图像求偏导矩阵,将该偏导矩阵累加到输入图像上,逐步迭代。
ps:个人见解,如有不当,请多指教。