图书馆(tensorflow)图书馆(keras)停止(“停止”)
DCGAN生成人脸图像
生成
一个简单的DCGAN训练使用
符合()
通过重写train_step
在CelebA的图片上。设置
准备CelebA数据
我们将使用来自CelebA数据集的人脸图像,大小调整为64x64。
<-fs::路径(“~ /数据/ celeba_gan”) dataset_path# output <- "celeba_gan/"如果(!fs::dir_exists(dataset_path)) {::dir_create(fs::path_dir(dataset_path)) fs<-“https://drive.google.com/uc?id=1O7m1010EJjLE5QxLZiM9Fpjs7Oj6e684” url::进口(“gdown”)$下载(url、输出安静的=真正的) 网状解压缩(输出,exdir =fs::path_dir(输出) }<-fs::路径(fs::path_dir(输出),“img_align_celeba”) dataset_path
从我们的文件夹创建一个数据集:
<-image_dataset_from_directory( 数据集 dataset_path,image_size =c(64,64),label_mode =零,batch_size =32 )<-数据集$应用(特遣部队$数据$实验$ignore_errors( 数据集log_warning =假 ))
让我们显示一个示例图像:
% > % 数据集::as_iterator()% > % 网状::iter_next()% > % 网状as.array()% > %1…]}% > % {。as.raster(max =255)% > %情节()
创建鉴别器
它将64x64图像映射到二进制分类分数。
<-keras_model_sequential(name =“鉴频器”,input_shape =形状(64,64,3.))% > % 鉴频器layer_conv_2d(64,kernel_size =4,进步=2,填充=“相同”)% > %layer_activation_leaky_relu(α=0.2)% > %layer_conv_2d(128,kernel_size =4,进步=2,填充=“相同”)% > %layer_activation_leaky_relu(α=0.2)% > %layer_conv_2d(128,kernel_size =4,进步=2,填充=“相同”)% > %layer_activation_leaky_relu(α=0.2)% > %layer_flatten()% > %layer_dropout(0.2)% > %layer_dense(1,激活=“乙状结肠”)总结(鉴别器)
创建生成器
它镜像鉴别器,进行替换conv_2d
层与conv_2d_transpose
层。
<-128升 latent_dim<-keras_model_sequential(input_shape =形状(latent_dim),name =“发电机”)% > % 发电机layer_dense(8*8*128)% > %layer_reshape(形状(8,8,128))% > %layer_conv_2d_transpose(128,kernel_size =4,进步=2,填充=“相同”)% > %layer_activation_leaky_relu(α=0.2)% > %layer_conv_2d_transpose(256,kernel_size =4,进步=2,填充=“相同”)% > %layer_activation_leaky_relu(α=0.2)% > %layer_conv_2d_transpose(512,kernel_size =4,进步=2,填充=“相同”)% > %layer_activation_leaky_relu(α=0.2)% > %layer_conv_2d(3.,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在潜在空间中随机采样点<-特遣部队$形状(real_images) [1] batch_size<-特遣部队$随机$正常的( random_latent_vectors形状=网状::元组(batch_size自我$latent_dim) )#解码为假图像<-自我$发电机(random_latent_vectors) generated_images#将它们与真实图像结合起来<-特遣部队$concat(列表(generated_images real_images),轴=0 l) combined_images#组装标签,区分真假图片<-特遣部队$concat( 标签列表($的(网状::元组(batch_size 1 l)), 特遣部队$0(网状::元组(batch_size 1 l)) 特遣部队 ),轴=0 l )#添加随机噪音标签-重要的技巧!<-标签+0.05*特遣部队$随机$统一的(特遣部队$形状(标签) 标签#训练鉴别器与(特遣部队$GradientTape()%, %胶带,{<-自我$鉴频器(combined_images) 预测<-自我$loss_fn(标签、预测) d_loss })<-磁带$梯度(d_loss自我$鉴频器$trainable_weights) 毕业生$d_optimizer$apply_gradients( 自我zip_lists(毕业生、自我$鉴频器$trainable_weights) )在潜在空间中随机采样点<-特遣部队$随机$正常的( random_latent_vectors形状=网状::元组(batch_size自我$latent_dim) )#组装标签,注明“所有真实图像”<-特遣部队$0(网状::元组(batch_size 1 l)) misleading_labels#训练生成器(注意,我们不应该更新权重#的鉴别器)!与(特遣部队$GradientTape()%, %胶带,{<-自我$鉴频器(自我$发电机(random_latent_vectors)) 预测<-自我$loss_fn(misleading_labels预测) g_loss })<-磁带$梯度(g_loss自我$发电机$trainable_weights) 毕业生$g_optimizer$apply_gradients(zip_lists(毕业生、自我$发电机$trainable_weights)) 自我#更新指标$d_loss_metric$update_state(d_loss) 自我$g_loss_metric$update_state(g_loss) 自我列表(“d_loss”=自我$d_loss_metric$结果(),“g_loss”=自我$g_loss_metric$结果() ) } )
创建一个回调,定期保存生成的图像
<-new_callback_class( gan_monitor“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) {<-特遣部队$随机$正常的(形状=形状(自我$num_img,自我$latent_dim)) random_latent_vectors<-自我$模型$发电机(random_latent_vectors) generated_images<-特遣部队$clip_by_value(generated_images*255,0,255) generated_images<-as.array(generated_images) generated_images为(我在seq_len(自我$num_img)) {image_array_save( generated_images(我…)sprintf(“dcgan / generated_img_ % 03 d_ % d.png”, epoch, i),规模=假 ) } } )
训练端到端模型
<-15#在实践中,使用~100个epoch 时代<-氮化镓(鉴频器=鉴频器,发电机=发电机,latent_dim =latent_dim) 氮化镓% > %编译( 氮化镓d_optimizer =optimizer_adam(learning_rate =1的军医),g_optimizer =optimizer_adam(learning_rate =1的军医),loss_fn =loss_binary_crossentropy(), )% > %适合( 氮化镓 数据集,时代=时代,回调函数=列表(gan_monitor(num_img =10,latent_dim =latent_dim) ) )
一些最后生成的图像大约是第15个纪元——每一行都是一个纪元。(之后成绩不断提高):
<-expand.grid(1:10,0:14) 网格::include_graphics(sprintf(“dcgan / generated_img_ % 03 d_ % d.png”、网格[[2网格]],[[1]])) knitr