1
+ """
2
+ Know more, visit my Python tutorial page: https://morvanzhou.github.io/tutorials/
3
+ My Youtube Channel: https://www.youtube.com/user/MorvanZhou
4
+
5
+ Dependencies:
6
+ tensorflow: 1.1.0
7
+ matplotlib
8
+ numpy
9
+ """
10
+ import tensorflow as tf
11
+ import numpy as np
12
+ import matplotlib .pyplot as plt
13
+
14
+ tf .set_random_seed (1 )
15
+ np .random .seed (1 )
16
+
17
+ # Hyper Parameters
18
+ BATCH_SIZE = 64
19
+ LR_G = 0.0001 # learning rate for generator
20
+ LR_D = 0.0001 # learning rate for discriminator
21
+ N_IDEAS = 5 # think of this as number of ideas for generating an art work (Generator)
22
+ ART_COMPONENTS = 15 # it could be total point G can draw in the canvas
23
+ PAINT_POINTS = np .vstack ([np .linspace (- 1 , 1 , ART_COMPONENTS ) for _ in range (BATCH_SIZE )])
24
+
25
+ # show our beautiful painting range
26
+ plt .plot (PAINT_POINTS [0 ], 2 * np .power (PAINT_POINTS [0 ], 2 ) + 1 , c = '#74BCFF' , lw = 3 , label = 'upper bound' )
27
+ plt .plot (PAINT_POINTS [0 ], 1 * np .power (PAINT_POINTS [0 ], 2 ) + 0 , c = '#FF9359' , lw = 3 , label = 'lower bound' )
28
+ plt .legend (loc = 'upper right' )
29
+ plt .show ()
30
+
31
+
32
+ def artist_works (): # painting from the famous artist (real target)
33
+ a = np .random .uniform (1 , 2 , size = BATCH_SIZE )[:, np .newaxis ]
34
+ paintings = a * np .power (PAINT_POINTS , 2 ) + (a - 1 )
35
+ labels = (a - 1 ) > 0.5 # upper paintings (1), lower paintings (0), two classes
36
+ labels = labels .astype (np .float32 )
37
+ return paintings , labels
38
+
39
+ art_labels = tf .placeholder (tf .float32 , [None , 1 ])
40
+ with tf .variable_scope ('Generator' ):
41
+ G_in = tf .placeholder (tf .float32 , [None , N_IDEAS ]) # random ideas (could from normal distribution)
42
+ G_art = tf .concat ((G_in , art_labels ), 1 ) # combine ideas with labels
43
+ G_l1 = tf .layers .dense (G_art , 128 , tf .nn .relu )
44
+ G_out = tf .layers .dense (G_l1 , ART_COMPONENTS ) # making a painting from these random ideas
45
+
46
+ with tf .variable_scope ('Discriminator' ):
47
+ real_in = tf .placeholder (tf .float32 , [None , ART_COMPONENTS ], name = 'real_in' ) # receive art work from the famous artist + label
48
+ real_art = tf .concat ((real_in , art_labels ), 1 ) # art with labels
49
+ D_l0 = tf .layers .dense (real_art , 128 , tf .nn .relu , name = 'l' )
50
+ prob_artist0 = tf .layers .dense (D_l0 , 1 , tf .nn .sigmoid , name = 'out' ) # probability that the art work is made by artist
51
+ # reuse layers for generator
52
+ G_art = tf .concat ((G_out , art_labels ), 1 ) # art with labels
53
+ D_l1 = tf .layers .dense (G_art , 128 , tf .nn .relu , name = 'l' , reuse = True ) # receive art work from a newbie like G
54
+ prob_artist1 = tf .layers .dense (D_l1 , 1 , tf .nn .sigmoid , name = 'out' , reuse = True ) # probability that the art work is made by artist
55
+
56
+ D_loss = - tf .reduce_mean (tf .log (prob_artist0 ) + tf .log (1 - prob_artist1 ))
57
+ G_loss = tf .reduce_mean (tf .log (1 - prob_artist1 ))
58
+
59
+ train_D = tf .train .AdamOptimizer (LR_D ).minimize (
60
+ D_loss , var_list = tf .get_collection (tf .GraphKeys .TRAINABLE_VARIABLES , scope = 'Discriminator' ))
61
+ train_G = tf .train .AdamOptimizer (LR_G ).minimize (
62
+ G_loss , var_list = tf .get_collection (tf .GraphKeys .TRAINABLE_VARIABLES , scope = 'Generator' ))
63
+
64
+ sess = tf .Session ()
65
+ sess .run (tf .global_variables_initializer ())
66
+
67
+ plt .ion () # something about continuous plotting
68
+ plt .show ()
69
+ for step in range (7000 ):
70
+ artist_paintings , labels = artist_works () # real painting from artist
71
+ G_ideas = np .random .randn (BATCH_SIZE , N_IDEAS )
72
+ G_paintings , pa0 , Dl = sess .run ([G_out , prob_artist0 , D_loss , train_D , train_G ], # train and get results
73
+ {G_in : G_ideas , real_in : artist_paintings , art_labels : labels })[:3 ]
74
+
75
+ if step % 50 == 0 : # plotting
76
+ plt .cla ()
77
+ plt .plot (PAINT_POINTS [0 ], G_paintings [0 ], c = '#4AD631' , lw = 3 , label = 'Generated painting' ,)
78
+ bound = [0 , 0.5 ] if labels [0 , 0 ] == 0 else [0.5 , 1 ]
79
+ plt .plot (PAINT_POINTS [0 ], 2 * np .power (PAINT_POINTS [0 ], 2 ) + bound [1 ], c = '#74BCFF' , lw = 3 , label = 'upper bound' )
80
+ plt .plot (PAINT_POINTS [0 ], 1 * np .power (PAINT_POINTS [0 ], 2 ) + bound [0 ], c = '#FF9359' , lw = 3 , label = 'lower bound' )
81
+ plt .text (- .5 , 2.3 , 'D accuracy=%.2f (0.5 for D to converge)' % pa0 .mean (), fontdict = {'size' : 15 })
82
+ plt .text (- .5 , 2 , 'D score= %.2f (-1.38 for G to converge)' % - Dl , fontdict = {'size' : 15 })
83
+ plt .text (- .5 , 1.7 , 'Class = %i' % int (labels [0 , 0 ]), fontdict = {'size' : 15 })
84
+ plt .ylim ((0 , 3 ))
85
+ plt .legend (loc = 'upper right' , fontsize = 12 )
86
+ plt .draw ()
87
+ plt .pause (0.1 )
88
+
89
+ plt .ioff ()
90
+
91
+ # plot a generated painting for upper class
92
+ plt .figure (2 )
93
+ z = np .random .randn (1 , N_IDEAS )
94
+ label = np .array ([[1. ]]) # for upper class
95
+ G_paintings = sess .run (G_out , {G_in : z , art_labels : label })
96
+ plt .plot (PAINT_POINTS [0 ], G_paintings [0 ], c = '#4AD631' , lw = 3 , label = 'G painting for upper class' ,)
97
+ plt .plot (PAINT_POINTS [0 ], 2 * np .power (PAINT_POINTS [0 ], 2 ) + bound [1 ], c = '#74BCFF' , lw = 3 , label = 'upper bound (class 1)' )
98
+ plt .plot (PAINT_POINTS [0 ], 1 * np .power (PAINT_POINTS [0 ], 2 ) + bound [0 ], c = '#FF9359' , lw = 3 , label = 'lower bound (class 1)' )
99
+ plt .ylim ((0 , 3 ))
100
+ plt .legend (loc = 'upper right' , fontsize = 12 )
101
+ plt .show ()
0 commit comments