DCGAN生成人脸图像

生成
一个简单的DCGAN训练使用符合()通过重写train_step在CelebA的图片上。
作者

fchollet

dfalbel- R翻译

设置

图书馆(tensorflow)图书馆(keras)停止“停止”

准备CelebA数据

我们将使用来自CelebA数据集的人脸图像,大小调整为64x64。

dataset_path<-fs::路径“~ /数据/ celeba_gan”# output <- "celeba_gan/"如果fs::dir_exists(dataset_path)) {fs::dir_create(fs::path_dir(dataset_path))url<-“https://drive.google.com/uc?id=1O7m1010EJjLE5QxLZiM9Fpjs7Oj6e684”网状::进口“gdown”下载(url、输出安静的=真正的解压缩(输出,exdir =fs::path_dir(输出)dataset_path<-fs::路径(fs::path_dir(输出),“img_align_celeba”

从我们的文件夹创建一个数据集:

数据集<-image_dataset_from_directorydataset_path,image_size =c6464),label_mode =batch_size =32数据集<-数据集应用(特遣部队数据实验ignore_errorslog_warning =))

让我们显示一个示例图像:

数据集% > %网状::as_iterator()% > %网状::iter_next()% > %as.array()% > %{。1…]}% > %as.rastermax =255% > %情节()

创建鉴别器

它将64x64图像映射到二进制分类分数。

鉴频器<-keras_model_sequentialname =“鉴频器”input_shape =形状64643.))% > %layer_conv_2d64kernel_size =4进步=2填充=“相同”% > %layer_activation_leaky_reluα=0.2% > %layer_conv_2d128kernel_size =4进步=2填充=“相同”% > %layer_activation_leaky_reluα=0.2% > %layer_conv_2d128kernel_size =4进步=2填充=“相同”% > %layer_activation_leaky_reluα=0.2% > %layer_flatten()% > %layer_dropout0.2% > %layer_dense1激活=“乙状结肠”总结(鉴别器)

创建生成器

它镜像鉴别器,进行替换conv_2d层与conv_2d_transpose层。

latent_dim<-128升发电机<-keras_model_sequentialinput_shape =形状(latent_dim),name =“发电机”% > %layer_dense88128% > %layer_reshape形状88128))% > %layer_conv_2d_transpose128kernel_size =4进步=2填充=“相同”% > %layer_activation_leaky_reluα=0.2% > %layer_conv_2d_transpose256kernel_size =4进步=2填充=“相同”% > %layer_activation_leaky_reluα=0.2% > %layer_conv_2d_transpose512kernel_size =4进步=2填充=“相同”% > %layer_activation_leaky_reluα=0.2% > %layer_conv_2d3.kernel_size =5填充=“相同”激活=“乙状结肠”总结(发电机)

覆盖train_step

氮化镓<-new_model_class“甘”初始化=函数(discriminator, generator, latent_dim) {超级()__init__()自我鉴频器<-鉴频器自我发电机<-发电机自我latent_dim<-latent_dim自我重新调节<-layer_rescaling规模=1/255},编译=函数(d_optimizer, g_optimizer, loss_fn) {超级()编译()自我d_optimizer<-d_optimizer自我g_optimizer<-g_optimizer自我loss_fn<-loss_fn自我d_loss_metric<-特遣部队keras指标的意思是name =“d_loss”自我g_loss_metric<-keras指标的意思是name =“g_loss”},指标=mark_active函数() {列表(自我d_loss_metric,自我g_loss_metric)}),train_step =函数(real_images) {real_images<-自我重新调节(real_images)在潜在空间中随机采样点batch_size<-特遣部队形状(real_images) [1random_latent_vectors<-特遣部队随机正常的形状=网状::元组(batch_size自我latent_dim)#解码为假图像generated_images<-自我发电机(random_latent_vectors)#将它们与真实图像结合起来combined_images<-特遣部队concat列表(generated_images real_images),轴=0 l)#组装标签,区分真假图片标签<-特遣部队concat列表特遣部队(网状::元组(batch_size 1 l)),特遣部队0(网状::元组(batch_size 1 l))),轴=0 l#添加随机噪音标签-重要的技巧!标签<-标签+0.05特遣部队随机统一的(特遣部队形状(标签)#训练鉴别器(特遣部队GradientTape()%, %胶带,{预测<-自我鉴频器(combined_images)d_loss<-自我loss_fn(标签、预测)})毕业生<-磁带梯度(d_loss自我鉴频器trainable_weights)自我d_optimizerapply_gradientszip_lists(毕业生、自我鉴频器trainable_weights)在潜在空间中随机采样点random_latent_vectors<-特遣部队随机正常的形状=网状::元组(batch_size自我latent_dim)#组装标签,注明“所有真实图像”misleading_labels<-特遣部队0(网状::元组(batch_size 1 l))#训练生成器(注意,我们不应该更新权重#的鉴别器)!(特遣部队GradientTape()%, %胶带,{预测<-自我鉴频器(自我发电机(random_latent_vectors))g_loss<-自我loss_fn(misleading_labels预测)})毕业生<-磁带梯度(g_loss自我发电机trainable_weights)自我g_optimizerapply_gradientszip_lists(毕业生、自我发电机trainable_weights))#更新指标自我d_loss_metricupdate_state(d_loss)自我g_loss_metricupdate_state(g_loss)列表“d_loss”自我d_loss_metric结果(),“g_loss”自我g_loss_metric结果()

创建一个回调,定期保存生成的图像

gan_monitor<-new_callback_class“gan_monitor”初始化=函数num_img =3.latent_dim =128 l) {自我num_img<-num_img自我latent_dim<-as.integer(latent_dim)如果fs::dir_exists“dcgan”) fs::dir_create“dcgan”},on_epoch_end =函数(epoch, logs) {random_latent_vectors<-特遣部队随机正常的形状=形状(自我num_img,自我latent_dim))generated_images<-自我模型发电机(random_latent_vectors)generated_images<-特遣部队clip_by_value(generated_images2550255generated_images<-as.array(generated_images)(我seq_len(自我num_img)) {image_array_savegenerated_images(我…)sprintf“dcgan / generated_img_ % 03 d_ % d.png”, epoch, i),规模=

训练端到端模型

时代<-15#在实践中,使用~100个epoch氮化镓<-氮化镓鉴频器=鉴频器,发电机=发电机,latent_dim =latent_dim)氮化镓% > %编译d_optimizer =optimizer_adamlearning_rate =1的军医),g_optimizer =optimizer_adamlearning_rate =1的军医),loss_fn =loss_binary_crossentropy(),氮化镓% > %适合数据集,时代=时代,回调函数=列表gan_monitornum_img =10latent_dim =latent_dim)

一些最后生成的图像大约是第15个纪元——每一行都是一个纪元。(之后成绩不断提高):

网格<-expand.grid110014knitr::include_graphicssprintf“dcgan / generated_img_ % 03 d_ % d.png”、网格[[2网格]],[[1]]))