https://www.tensorflow.org/api_docs/python/tf/layers/batch_normalization https://www.tensorflow.org/programmers_guide/variableshttps://www.tensorflow.org/programmers_guide/variables https://www.tensorflow.org/api_guides/python/reading_data#Multiple_input_pipelines
主要是tf.name_scope, tf.variable_scope, tf.get_variable, tf.Variable,tf.op_scope
op_scope和variable_op_scope:
在r0.11版本已经废弃,并且替换为name_scope
和variable_scope
.
查阅官方API文档https://www.tensorflow.org/api_docs/python/tf/variable_op_scope,
https://www.tensorflow.org/api_docs/python/tf/op_scope
确实如此。
tf.name_scope, tf.variable_scope, tf.get_variable, tf.Variable: What's the difference of name scope and a variable scope in tensorflow? tensorflow scope命名方法(variable_scope()与name_scope()解析 看完这两篇文章就知道怎么用了。简单来讲就是下面三段代码:
with tf.name_scope("my_scope"):
v1 = tf.get_variable("var1", [1], dtype=tf.float32)
v2 = tf.Variable(1, name="var2", dtype=tf.float32)
a = tf.add(v1, v2)
print(v1.name) # var1:0
print(v2.name) # my_scope/var2:0
print(a.name) # my_scope/Add:0
with tf.variable_scope("my_scope"):
v1 = tf.get_variable("var1", [1], dtype=tf.float32)
v2 = tf.Variable(1, name="var2", dtype=tf.float32)
a = tf.add(v1, v2)
print(v1.name) # my_scope/var1:0
print(v2.name) # my_scope/var2:0
print(a.name) # my_scope/Add:0
with tf.name_scope("foo"):
with tf.variable_scope("var_scope"):
v = tf.get_variable("var", [1])
with tf.name_scope("bar"):
with tf.variable_scope("var_scope", reuse=True):
v1 = tf.get_variable("var", [1])
assert v1 == v
print(v.name) # var_scope/var:0
print(v1.name) # var_scope/var:0
tf.name_scope
下,tf.Variable
受影响,tf.get_variable
不受影响。tf.variable_scope
下,tf.Variable
和tf.get_variable
都受影响。name_scope
下轻松地共享同一变量。另外就是,tf.Variable
每次调用都会创建新的变量,而tf.get_variable
会在没有该变量时创建;而在已创建该变量时,调用reuse
就可以复用该变量(如果不调用reuse就会报错)。此次项目的构造是基于DCGAN的。
本节会依次讲解GAN和DCGAN。在下一节介绍项目所采用的,基于DCGAN改造的网络。
GAN构造图
另一个GAN的示例
GAN即生成对抗网络,分为生成器和辨别器两个网络:
整个网络的训练需要同时训练两个网络,这两个网络的目标是相互对立的:
训练目标: 经过多次的“攻防”训练,生成器和辨别器都会达到很高的水平,最终当生成器生成的图片难以被辨别器识别,辨别器只能靠1/2的概率瞎猜时,训练就完成了。
DCGAN结构图
DCGAN(Deep Convolutional Generative Adversarial Networks)原理是和GAN一样的,只是把G和D用卷积神经网络实现而已。但DCGAN的网络具有以下特点:
总的来说,数据的流动如下:
如果是普通的GAN,那么D只要负责判断G的生成图片是真是假就行。 D只需接受两种数据:
但是在这个任务中,G要生成符合t描述的图像,就要使用GAN-CLS。在GAN-CLS中,D应当判断出真实图像,且图像要符合文字描述。 此时D需要接受三种数据:
这样训练出来的辨别器不仅能判断图像是否真实,还能判断图像与文字描述是否吻合。
论文认为,深度网络学习到的特征表示其实具有可插值性——如果有一对文字描述的深度特征和它们对应的两张图片,那么我们经过差值合成一个新的特征,这个特征所生成的图片也应当与那两张图片相近。 也就是说,”一只小鸟在天上飞”和”黑头乌龟在地上晒太阳”,它们的深度特征插值后,没准就成了“一只黑头小鸟在地上晒太阳了”。
于是论文提出了GAN-INT:
GAN-INT的生成器的目标
其中t1和t2是两个文本,β是差值比例。生成器的目标是:用某种比例合成两个文本,并根据合成文本生成图像,图像要尽可能贴合这个合成文本。通过合成文本,并调整β参数,我们可以得到理论上无数的文本数据,并用它训练D和G。(根据经验,β=0.5时效果不错)
所以,尽管差值后的合成特征没有对应的真实图片(当然没有,因为特征本来都是合成的),我们仍然可以用合成特征搭配真实图片来训练辨别器D,在训练过程中,辨别器将更善于判断图片与文字描述是否匹配,反过来,能够促使生成器G生成更符合文字描述的图片
很多时候,文本描述只是定义了图片的content信息,而没涉及style信息(比如鸟的姿势,背景颜色)。所以我们就希望z能起到调整style的作用。于是论文就训练了一个invertG:G将文本转换为图片,而invertG把图片再转换回文本。
style的损失函数
然后作者把图片按照style进行聚类(平均背景颜色,鸟类姿态等),然后取属于同一聚类的样本,求得z。通过求解相同聚类的图片的style表示z之间的consine距离,从而确定不同训练方式,z所起到的style作用的强弱。
上图显示,不管是在姿势还是在背景颜色上,GAN-INT-CLS和GAN-INT的噪声向量z都起到更大的作用。而在整体表现上,使用了文本差值方法的GAN(GAN-INT、GAN-INT-CLS)都表现得更好。
h5py结构
h5py把存储的数据看做两种:dataset和group。dataset就相当于文件,group就相当于文件夹。group可以包含dataset和其它group,就好比文件夹里可以包含文件和其它文件夹。 h5py文件的读写,只需要类似如下操作即可:
import h5py
h = h5py.File("myh5py.hdf5","w")
h.create_dataset('any_key', data='123') # 保存数据“123”到“any_key”的索引下
h.close()
f = h5py.File("myh5py.hdf5","r")
value = f['any_key']
print(value) # 输出123
skip-thought vectors是一个github上的自然语言项目,它的作用是把一个句子转换成固定维度的向量(长度为4800),并且意思相近的句子所转换成的向量也相距较近。 转换成的向量都是长度为4800的combine-skip model,其中前2400称为uni-skip model,后2400称为bi-skip model。作者推荐使用完整的4800长度向量进行计算,因为这样能达到更好的效果。
text-to-image的网络结构
网络的实现是如下形式的:
而两个网络的目标也不同于传统的DCGAN:
也就是说,辨别器的训练会接受三种数据:
我在参考了文章后,主要做了以下改造: