DeepDreamDeepDream生成式深度学习DeepDream简介DeepDream是一种艺术图像修饰技术,主要基于训练好的卷积神经网络(CNN)进行图像生成。在生成图片的时候,神经网络是冻结的,即不再更新网络的权重,只需要更新输入的图片。常用的预训练卷积网络包括谷歌的Inception、VGG网络和ResNet网络。DeePDream的基本步骤:获取输入图片,将图片输入网络,获取你要可视化的神经元的输出值,计算神经元的输出值,利用图片每个像素的梯度下降来不断更新图片,重复步骤2、3、4,直到满足设定条件以下是使用Keras实现DeepDream的大致流程:使用Keras实现DeepDream获取测试图片在[1]中:#--------------从tensorflow导入kerasimportmatplotlib。pyplotasplt%matplotlibinlinebase_image_path=keras.utils.get_file("coast.jpg",origin="https://img-datasets.s3.amazonaws.com/coast.jpg")plt.axis("off")plt.imshow(keras.utils.load_img(base_image_path))plt.show()上面是Keras自带的海岸线图。下面是这张图的改动。准备预训练模型InceptionV3In[2]:#使用InceptionV3实现fromkeras.applicationsimportinception_v3#使用预训练的ImageNet权重加载模型model=inception_v3.InceptionV3(weights="imagenet",#构建一个不包含全连接层的模型Inceptinoinclude_top=False)从https://storage.googleapis.com/tensorflow/keras-applications/inception_v3/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h587916544/87910968下载数据[================================]-74s1us/step87924736/87910968[==================================]-74s1us/stepIn[3]:model.summary()setDeepDreamconfigurationIn[4]:#层名+系数:贡献度layer_settings={"mixed4":1.0,"mixed5":1.5,"mixed6":2.0,"mixed7":2.5}outputs_dict=dict([(layer.name,layer.output)#层名称+该层的输出forlayerin[model.get_layer(name)fornameinlayer_settings.keys()]])outputs_dictOut[4]:{'mixed4':,'mixed5':,'mixed6':,'mixed7':}In[5]:#特征提取feature_extractor=keras.Model(inputs=model.inputs,outputs=outputs_dict)feature_extractorOut[5]:calculatelossIn[6]:defcompute_loss(image):features=feature_extractor(image)#特征提取loss=tf.zeros(shape=())#lossinitializationfornameinfeatures.keys():#traversallayercoeff=layer_settings[name]#something某一层的激活系数=features[name]#某层的激活函数#为了避免边界伪影,损失中只包含非边界像素loss+=coeff*tf.reduce_mean(tf.square(activation[:,2:-2,2:-2,:]))#将这一层的L2范数加入到loss中;returnlossgradientascentprocessIn[7]:importtensorflowastf@tf.functiondefgradient_ascent_step(image,lr):#lr--->learning_ratelearningratewithtf.GradientTape()astape:tape.watch(image)loss=compute_loss(image)#调用计算损失方法grads=tape.gradient(loss,image)#梯度更新grads=tf.math.l2_normalize(grads)image+=lr*gradsreturnloss,imagedefgradient_ascent_loop(image,iterations,lr,max_loss=None):foriinrange(iterations):loss,image=gradient_ascent_step(image,lr)ifmax_lossisnotNoneandloss>max_loss:breakprint(f"Thelossvalueofstep{i}is{loss:.2f}")returnimage图像生成np.expand_dimsusage(个人添加)In[8]:importnumpyasnparray=np.array([[1,2,3],[4,5,6]])arrayOut[8]:array([[1,2,3],[4,5,6]])In[9]:array.shapeOut[9]:(2,3)In[10]:array1=np.expand_dims(array,axis=0)array1Out[10]:array([[[1,2,3],[4,5,6]]])在[11]中:array1。shapeOut[11]:(1,2,3)In[12]:array2=np.expand_dims(数组,axis=1)array2Out[12]:array([[[1,2,3]],[[4,5,6]]])In[13]:array2.shapeOut[13]:(2,1,3)In[14]:array3=np.expand_dims(array,axis=-1)array3Out[14]:array([[[1],[2],[3]],[[4],[5],[6]]])In[15]:array3.shapeOut[15]:(2,3,1)np.clip函数(个人补充)np.clip(array,min(array),max(array),out=None):In[16]:array=np.array([1,2,3,4,5,6])np.clip(array,2,5)#输出长度与原始数组Out[16]:array([2,2,3,4,5,5])In[17]:array=np.arange(18).reshape((6,3))arrayOut[17]:数组([[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13,14],[15,16,17]])In[18]:np.clip(array,5,15)Out[18]:array([[5,5,5],[5,5,5],[6,7,8],[9,10,11],[12,13,14],[15,15,15]])参数设置In[19]:step=20.#梯度上升的步长num_octave=3#尺度数torungradientascentoctave_scale=1.4#两个尺度迭代之间的比率=30#在每个尺度上运行梯度上升的步数max_loss=15.#如果loss值大于15,梯度上升过程会被打断ProcessingIn[20]:importnumpyasnpdefpreprocess_image(image_path):#Preprocessimg=keras.utils.load_img(image_path)#Importimageimg=keras.utils.img_to_array(img)#转换为数组img=np.expand_dims(img,axis=0)#增加数组维度;见上面解释(x,y)---->(1,x,y)img=keras.applications.inception_v3.preprocess_input(img)returnimgdefdeprocess_image(img):#图像压缩处理img=img.reshape((img.shape[1],img.shape[2],3))img/=2.0img+=0.5img*=255.#np.clip:截断函数,保证数组中的值在0-255之间img=np.clip(img,0,255).astype("uint8")returnimg生成图片In[21]:#step=20.#梯度上升步长Long#num_octave=3#尺度数运行梯度上升#octave_scale=1.4#两个尺度之间的比率#iterations=30#每个尺度上运行梯度上升的步数#max_loss=15.0#如果损失值大于15,则中断梯度上升过程original_img=preprocess_image(base_image_path)#预处理函数original_shape=original_img.shape[1:3]print(original_img.shape)#四维图像print(original_shape)#第二和第三维的值(1,900,1200,3)(900,1200)在[22]中:successive_shapes=[original_shape]foriinrange(1,num_octave):shape=tuple([int(dim/(octave_scale**i))fordiminoriginal_shape])successive_shapes.append(shape)successive_shapes=successive_shapes[::-1]#翻转shrunk_original_img=tf.image.resize(original_img,successive_shapes[0])img=tf.identity(original_img)fori,shapeinenumerate(successive_shapes):print(f"Processingoctave{i}withshape{shape}")#调整img大小=tf.image.resize(img,shape)img=gradient_ascent_loop(#阶梯上升函数调整用img,iteratinotallow=iterations,lr=step,max_loss=max_loss)#resizeupscaled_shrunk_original_img=tf.image.resize(shrunk_original_img,shape)same_size_original=tf.image.resize(original_img,shape)lost_detail=same_size_original-upscaled_shrunk_original_imgimg+=lost_detailshrunk_original_img=tf.image.resize(original_img,shape)keras.utils.save_img("dream.png",deprocess_image(img.numpy()复制代码))结果为:Processingoctave0withshape(459,612)lossatstep0is0.80lossatstep1lossatstep2is1.44lossatstep3is1.82...26第一步的损失值为11.44损失值第27步的loss值为11.72第28步的loss值为12.03第29步的loss值为12.49同时在本地生成一张新图,看效果:再看一下原图:对比下,新图有点梦幻!