ã®ç¶ç·¨ã
ããããè²ã ãªå¤æ´ãã¤ã¤å®é¨ãã¦ã¿ããããã®ã§ãã®è¨é²ã çµè«ãå ã«æ¸ãã¨ããããããæ¹åããã
DCGAN ãã£ãããããã
- Generator: ä¹±æ°ã®å ¥åããç»åãçæãã
- Discriminator: å ¥åããç»åãGeneratorãçæãããã®ãå¦ç¿ãã¼ã¿ã®ãã®ããå¤å¥ãã
ã¨ãã2種é¡ã®ãããã¯ã¼ã¯ãç¨æãããäºããé¨ãã»è¦ç ´ãããã«å¦ç¿ãè¡ããã¨ã§ Generatorãå¦ç¿ãã¼ã¿ãã£ããã®ç»åãçæã§ããããã«ãªããã¨ãããã®
å¦ç¿ç¨ç»åã®å¢å
ååã®è¨äºã§ã¯90人ã®é¡ç»åãã¼ã¿ããçæãã¦ãããã©ãããããåéãç¶ã㦠ããå°ãå¤ãéã¾ã£ãã®ã§ãä»åã¯260人ããéããé¡ç»å100ç¹ãã¤ãè¨26,000件ãå¦ç¿ã«ä½¿ç¨ããã
Feature matching
ã®è¨äºã§ç´¹ä»ããã¦ãã "Improved Techniques for Training GANs" ã¨ããè«æãèªãã§ã使ãããã³ã¼ããèªãã§ã¿ã¾ãã¦ãæ£ç´ä½ãã£ã¦ããã®ãåãããªãé¨åãå¤ãç解ã§ãã¦ããªããã¨ã ãããªã®ã ãã© ãã®ä¸ã® "3.1 Feature matching" ã®ã¨ããã¯åãããããå¹ãããã ã£ãã®ã§åãå ¥ãã¦ã¿ãã
åçã¨ãã¦ã¯ããDiscriminatorã®ä¸é層åºåã«ã¯åé¡ã®ããã®ç¹å¾´(feature)ãå«ã¾ããã¯ããªã®ã§ããããGeneratorã«ãããã®ã¨å¦ç¿ãã¼ã¿ç±æ¥ã®ãã®ã¨ã§ä¼¼ããããªãã®ã«ãªã£ã¦ããã°(å¦ç¿ãã¼ã¿ã«è¿ããã®ãGeneratorããçæããã¦ãããã¨ãããã¨ã«ãªãã®ã§)ããè¯ãã¯ããã¨ãããã¨ã®ããã ã
ãªã®ã§ãDiscriminatorã®æçµåºå(å ¥åç»åãå¦ç¿ãã¼ã¿ã®ãã®ãå¦ããå¤å®ãããã®)ã®1ã¤åã®ã4åã®ç³ã¿è¾¼ã¿ãè¡ã£ã段éã§ã®åºåããããã(Generatorç±æ¥ã®ç»åãå ¥åããå ´å/å¦ç¿ãã¼ã¿ã®ç»åãå ¥åããã¨ã)ã§åå¾ããåmini batchãã¨ã®å¹³åå¤ã®å·®åãå°ãªããªããã é©å½ãªåçãæãã¦Generatorã®losså¤ã¨ãã¦å ããã
def build(self, input_images, learning_rate=0.0002, beta1=0.5, feature_matching=0.0): """build model, generate losses, train op""" generated_images = self.g(self.z)[-1] outputs_from_g = self.d(generated_images) outputs_from_i = self.d(input_images) logits_from_g = outputs_from_g[-1] logits_from_i = outputs_from_i[-1] if feature_matching > 0.0: ), feature_matching)) features_from_g = tf.reduce_mean(outputs_from_g[-2], reduction_indices=(0)) features_from_i = tf.reduce_mean(outputs_from_i[-2], reduction_indices=(0)) tf.add_to_collection('g_losses', tf.mul(tf.nn.l2_loss(features_from_g - features_from_i), feature_matching)) tf.add_to_collection('g_losses', tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits_from_g, tf.ones([self.batch_size], dtype=tf.int64)))) tf.add_to_collection('d_losses', tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits_from_i, tf.ones([self.batch_size], dtype=tf.int64)))) tf.add_to_collection('d_losses', tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits_from_g, tf.zeros([self.batch_size], dtype=tf.int64))))
å¾è¿°ããããã©ãå¾æ¥ã®æ¹æ³ã 㨠å¦ç¿ãç¶ãã¦ããã¨çæç»åãå ¨ä½çã«ç½ã£ã½ãèããªããã¨ããç¾è±¡ããã£ã¦ãããããããã¯Discriminatorãç»åãå¤å¥ããéã«å ¨ä½ã®è²åããªã©ã¯æ³¨è¦ããªããããªã®ã§ã¯ãªããã¨æãã(以åã®è¨äºã§å®é¨ãã¦ããããã«ã人éã®æè¦ã¨ã¯å ¨ç¶éãç¹å¾´æ½åºãã¦ããããã )ã ãããé²ãããã«ã ãã®feature matchingã¨åæ§ã®ãã®ãæçµåºåã®ç»åã«ãé©ç¨ãã¦ã¿ãã
logits_from_g = outputs_from_g[-1] logits_from_i = outputs_from_i[-1] if feature_matching > 0.0: + mean_image_from_g = tf.reduce_mean(generated_images, reduction_indices=(0)) + mean_image_from_i = tf.reduce_mean(input_images, reduction_indices=(0)) + tf.add_to_collection('g_losses', tf.mul(tf.nn.l2_loss(mean_image_from_g - mean_image_from_i), feature_matching)) features_from_g = tf.reduce_mean(outputs_from_g[-2], reduction_indices=(0)) features_from_i = tf.reduce_mean(outputs_from_i[-2], reduction_indices=(0)) tf.add_to_collection('g_losses', tf.mul(tf.nn.l2_loss(features_from_g - features_from_i), feature_matching))
æ¯è¼çµæã以ä¸ã®åç»ãå·¦å´ãå¾æ¥ã®æ®éã®DCGANãå³å´ãfeature matchingãå ãããã®ã
å·¦å´ã¯å ¨ä½çã«ãã£ã¨ã¬ãã£ã¬ãã£ã¨ç®ã¾ããããå¤åãã¦ãã¦è½ã¡çããªãæããªã®ããå³å´ã¯æ¯è¼çæ©ã段éããé¡ã£ã½ããã®ãåºæ¥ã¦ããããã«å®å®ãã¦ããããã«å¤åãã¦ããæ§åã伺ãããã¾ãå·¦ã¯14,000stepãããããå ¨ä½çã«ç½ã£ã½ãèããªã£ã¦ãã£ã¦ããã®ã å³å´ã§ã¯èµ·ãããªããªã£ã¦ããã®ã確èªã§ããã
Learning rate, Batch size
ãããä¸è¨ã®æ¹æ³ã§ãã©ãã«ãéçããããã㧠ããç¨åº¦ã¾ã§ã¯ãã¬ã¤ã«é¡ã£ã½ããã®ãçæããããã«ãªã£ã¦ããã¾ã ã¾ã å´©ãããã®ã«ãªã£ã¦ãã¾ãå ´åãå¤ãã å¤åã観å¯ãã¦ããã¨10,000stepãããã§ãããªãã®ã¯ãªãªãã£ã«ãªã£ã¦ãããããã¯30,000stepãããã¾ã§ç¶ãã¦ããã¾ãå¤åãè¦ãããªããã¨ããæãã ã£ãã
ã©ãã«ããã£ã¨è¯ãç»åãçæãããããã«æ¹åãããªãããã¨learning_rate
ãããã©ã«ãããå°ããã«ãã¦ã¿ãããbatch_size
ã128
ãããã£ã¨å¤§ãããã¦ã¿ããããããã©ãçµå±ã©ããããã»ã©å¹æã¯ç¡ãããã ã£ãã
Discriminatorã®åºåãè¦ã
ã¨ã¯ãã Generatorã¯ç¡éã®ä¹±æ°å ¥åããç¡éã®ãã¿ã¼ã³ãçæããããã§ããã¹ã¦ããã¬ã¤ãªé¡ç»åã«ãªãããããªã ã¨ããã®ã¯å½ããåã¨ããã°å½ããåããªãã°è¤æ°çæããããã®ããä¸æããã£ããã®ã ãèªåã§æ½åºã§ããã°è¯ãã®ã§ã¯ï¼
ã¨ãããã¨ã§å¦ç¿æ¸ã¿ã®Generatorã¨Discriminatorã使ã£ã¦ãmini batchã§çæãããè¤æ°ã®ç»åãDiscriminatorã«éããçµæã®softmax
å¤ã®é«ãé ã«è¡¨ç¤ºãã¦ã¿ãã
# ä¹±æ°mini batchããç»åãçæãã images = sess.run(dcgan.g(dcgan.z)[-1]) # discriminatorã®åºåã«softmaxããããã®ãå転ãã¦top_kãæ½åº # `0`ãé«ãåºåãããã® `1`ãé«ãåºåãããã® ä¸ä½10件ãã¤ã®å¤ã¨indexãåãã values, indices = tf.nn.top_k(tf.transpose(tf.nn.softmax(dcgan.d(images)[-1])), 10) for x in sess.run([values, indices]): print(x.tolist()) # top_kã§å¾ãindicesã使ã£ã¦çæç»åããæ½åºãã縦横ã«é£çµ rows = [] for cols in tf.split(0, 2, tf.gather(images, indices)): rows.append(tf.concat(3, tf.split(1, 10, cols))) result = tf.squeeze(tf.concat(2, rows), [0, 1]) # ä½è¨ãªæ¬¡å ãåæ¸ãã¦jpegç»åã«å¤æãã¦åºå img = tf.image.encode_jpeg(tf.image.convert_image_dtype((result + 1.0) / 2.0, tf.uint8)) filename = os.path.join(FLAGS.images_dir, 'out.jpg') with open(filename, 'wb') as f: print('write to %s' % filename) f.write(sess.run(img))
ä¸æ®µããDiscriminatorã®softmaxåºåã0
ã§é«ãã£ããã®ä¸ä½ãèªåã®DCGANå®è£
ã§ã¯ããã¯DiscriminatorãGeneratorã«ããç»åã ã¨å¤å®ãããã®ãä¸æ®µããsoftmaxåºåã1
ã§é«ãã£ããã®ä¸ä½ ããªãã¡å¦ç¿ãã¼ã¿ã¨å¤å®ããããã®(ãã¾ãé¨ãããã®)ãã¨ãªãã
ãã¼ãã確ãã«ä¸æ®µã®ãã®ã®æ¹ããã¬ã¤ã«åºæ¥ã¦ãããã®ãå¤ããããªæ°ããããã©ãå¥ã«å ¨é¨ãè¯ãããã§ããªãã ä¸æ®µã«ããããªãã®ãã®ãåºã¦ãã¦ããããã⦠ããã以åã®è¨äºã§ç¢ºèªããéããã¢ãã«ãå¤å¥ããç¹å¾´ã¯äººéã®æè¦ã¨å ¨ç¶ã¡ãããããã¾ãå½ã¦ã«ã¯ãªããªããã®ããç¥ããªãâ¦ã
Web UIã§å ¥åºåã調ã¹ã
ãªãã°å ¥åã®å¤ãå¼ã£ã¦ã©ãã«ããããã¨ã¯ã§ããªãããã¨æã£ãã®ã ãã© Generatorã¯ãã©ãã¯ããã¯ã¹ããã¦ãã©ããªå¤ãå ¥åãã㨠ã©ããªç»åãçæããããããç´æçã«ã¯ã¾ã£ããåãããªãã
ã®ã§ãå ¥åå¤ãè²ã å¤ãã¦å®é¨ã§ãããã ãããªWeb UIãä½ã£ã¦ã¿ãã
å
¥åä¹±æ°ã16次å
ã®æ°å¤ã¨ãã¦ããããã¯å®éã«ã¯å°æ°å¤ãªã®ã ãã©åãããããããã«0
-255
ã®æ´æ°å¤ã«ç½®ãæãã¦ã¹ã©ã¤ãã¼ãªã©ã§æä½ã§ããããã«ããããã®å¤ã«å¿ãã¦APIçµç±ã§ãã®å
¥åå¤ããGeneratorã«ããé¡ç»åçæãè¡ãçµæãæç»ããã®ã¨ãã®å
¥åå¤ã32æåã®hex stringã§è¡¨ç¾ãã¦åç¾ã«ä½¿ããããã«ããã
ã¨ãããã®ãReactã¨ãåå¼·ããªããMaterial-UIã§ä½ã£ã¦ã¿ãã
å ¥åå¤ãæä½ãã
ãã®UIã§è²ã ã¨ã©ã³ãã ãªå ¥åã§è©¦ãã¦ã¿ãã¨ãä¾ãã°ãããå´©ããé¡ãã©ããªå ¥åããçã¾ããã®ããææ¡ã§ããã
82763953b2740fef4d321dde7af002f7
75cd0382329c4a341e296530c615b674
54795b1ef616f55d2cd32f288a3f41f2
ã¨ããæãã«ã ããããå¹¾ã¤ãæ½åºãã¦éã«å¹³åãåã£ã¦ã¿ãã¨
samples = %w( 82763953b2740fef4d321dde7af002f7 75cd0382329c4a341e296530c615b674 54795b1ef616f55d2cd32f288a3f41f2 b21ce031415c8abb73d8200bc115476c b0064a3e5ec757ae09898814edd94264 2e790129bd66adfc8796201ff947259a 097c5a73700498603e43ab439a854a83 2a57676c479b4953d1694c45074229a2 584bcb88c0609c61161ef62cab740b98 725f3fe61612a4becf920302e936b022 618b23b2189ea810998968b7dc60e4b5 0f254708a300a458f504d97fcba07442 ) lists = samples.map do |hex| hex.scan(/.{2}/).map(&:hex) end avg = lists.transpose.map do |a| a.inject(&:+).to_f / a.size end puts avg.map { |e| format('%02x', e) }.join
$ ruby average.rb 5b605461755d86826d6b6348b168598d
ã¨ããã®ãå¾ããããããå ¥åã¨ãã¦ä½¿ã£ã¦ã¿ãã¨â¦
5b605461755d86826d6b6348b168598d
ã¨ããããé¡ã¨ãåãããªããããªãããã®ãåºåããããã¨ãåããã
éã«ããããããã¬ã¤ã«ä¸æãçæããããã®ãéãã¦å¹³åãåã£ã¦ã¿ãã¨
samples = %w( e7a8fea0affc366aa0fc77911c54201a c5c3ede294e988a1e8ebb7941def3297 a1b3f8d8be647c6775cd94e184bb4f08 75dcabe39c9f8b7e908ecd88546e2c9d a582debdcf74d579b990ce7123a48675 ede6a4fc6cdab7828677e7dd6a998880 d6e1a99db03f44a29fc49c9427c70569 fcd35bd348836cc7a18d92d29367196c e789ec78b2cf2ba5e5bd9f87723e913f f788ded2733f4eb7e7fa9acc2a4aae26 b2c5b8d3a6b54bd5e7e1cc90838774cf dcd9b5bb87a86ec8c3dbace763a65d5c c8f8a9e199e244e0f59ab4db62466783 ) lists = samples.map do |hex| hex.scan(/.{2}/).map(&:hex) end avg = lists.transpose.map do |a| a.inject(&:+).to_f / a.size end puts avg.map { |e| format('%02x', e) }.join
cbbfc4c798a26ba1babeaeaf53865766
ã¨ãã¨ã¦ãèªç¶ãªã¤ã¤ã«ã³ã¸ã®ç»åãçæããããã¨ã確èªã§ããã
ãã®ãè¯ãä¾ãã¨ãæªãä¾ãã®å·®åãåã£ã¦ããæªãå ¥åããããè¯ãå ¥åãã¸åãããã¯ãã«ãä¹±æ°å ¥åå¤ã«ãªãã»ããã¨ãã¦å ãã¦ããã°ãããè¯ãçµæãçã¾ããããã®ã§ã¯ï¼ï¼ ã¨ãããã¨ã§ãã£ã¦ã¿ãçµæãããã
å ¥åå¤ã®ç¯å²ãçãããããã¨ã§ ã¡ãã£ã¨ä¼¼ããå¯ã£ãããªãã®ãå¤ããããªæ°ãããªãã§ããªããã©ãããé«ç¢ºåº¦ã§æ¯è¼çå®å®ããé¡ç»åãå¾ãããããã«ãªã£ãã ä¸å¿ã¡ããã¨ãããã髪åãé¡ã®è§åº¦ã»è¡¨æ ã¯éã£ã¦ããããæªããªãã¨æãã
ãã®ãå ¥åå¤ã«ãªãã»ãããå ãããææ³ã§ãä¾ãã°ãå·¦åãã®é¡ãåºåãããå ¥åããå³åãã®é¡ãåºåãããå ¥åãã調ã¹ã¦å·®åãã¯ãã«ãå ¥åå¤ã«å ãããã¨ã§å³åãã°ããã®ãã®ãçæãããããã«ãªã£ããã表æ ã髪ã»èã®è²ã¨ã è²ããªè¦ç´ ã調ç¯ãã¤ã¤çæã§ããããã«ãªããã¨ãæå¾ ã§ããã(ã¾ã ããã¾ã§ã¯åºæ¥ã¦ããªãããããã£ãç¹å¾´ãæ½åºããã®ããªããªãé¢åâ¦ã)
ä»å¾ã®å±æ
ããã¡ãã£ã¨ãå ¥åå¤ã®è¯ãåãæ¹ãªã©ã¯ç 究ãã¦ã¿ããã¨ãããé髪ã¨ãã·ã§ã¼ãã¨ãé¢ãç®ã¨ãç¬é¡ã¨ããæ§ã ãªæåãæå®ãã¦èªç±ã«èªå好ã¿ã®é¡ãçæã§ããããã«ãªããã®ãç®æ¨ããªã
ãã¨ã¯è¤æ°ã®é¡ãã¢ã¼ãã£ã³ã°ã§é·ç§»ããã¢ãã¡ã¼ã·ã§ã³ã¨ãä½ãã¨é¢ç½ããã ã¨æã£ã¦ããã®ã§ãããããã®ãçæããUIãä½ã£ã¦ã¿ããã¨æã£ã¦ããã
ããããDCGANã§ã®çæããããéçãªã®ãã©ãããããã«æ¹è¯ããæ¹æ³ããã¾ãDCGANã§ã¯ãªãçææ¹æ³ã調ã¹ã¦è©¦ãã¦ã¿ããã¨ããã