GAN中包含两个模型:生成模型(Generative Model)和判别模型(Discriminative Model)。
生成模型通过反卷积神经网络将随机输入值转化为图像。
判别模型是一个分类器,它判断给定的图片到底是来自数据集的真实图像,还是人工创建的假图像。这基本上就是一个表现为卷积神经网络(CNN)形式的二元分类器。
GAN可以用任何形式的generator和discriminator,不一定非得使用神经网络。
在数次训练迭代的历程中,判别器和生成器的的权重和偏差都是通过反向传播训练的。判别器学习从一堆生成器生成的假数字图像中,找出真正的数字图像。与此同时,生成器通过判别器的反馈学习如何生成具有欺骗性的图片,防止被判别器识别出来。
生成网络:
输入为随机数,输出为生成数据。比如说,输入一个一维随机数,输出一张 28x28 (784 维) 的图片 (MNIST)。
网络实现用最 vanilla 的多层神经网络即可。记得不宜超过三层,否则梯度消失梯度爆炸的问题你懂的。中间的激活函数用当下最时兴的 Relu 就好。输出层需要使用其他激活函数,目的是为了生成数据的取值范围与真实数据相似,具体使用什么函数视情况而定。下面给出一个可能的实现方案:
判别网络:
现在,我们把生成网络生成的数据称为假数据,对应的,来自真实数据集的数据称为真数据。判别网络输入为数据(真或假),输出一个判别概率。需注意的是,这里判别的是图像的真伪,而非图像的类别。还以 MNIST 为例。输入一个图片后,我们并不要认图片上画的是啥数字,而是判别图像到底来自于真实数据集,还是生成网络的胡乱合成。所以输出一个一维条件概率(伯努利分布的概率参数)就好了。
网络实现同样可用最基本的多层神经网络。下面给出一个可能的方案。
loss 函数:
既然有俩网络,那么我们就有俩 loss 函数对应之。生成网络用
交叉熵:因为我们总是用one-hot来表示输出结果,实际上,这个one-hot也是有拟合度的是不是,如果过分平均,只有某项以微弱优势胜出的话,那么说明判别器拿不准,交叉熵就是体现这种关系的。
经典误差就是 错误的/所有的,非常直观,但真的损失了很多信息。
均方误差就是挨个相减的平方取平均
那为什么不采样这种损失函数呢?主要原因是逻辑回归配合MSE损失函数时,采用梯度下降法进行学习时,会出现模型一开始训练时,学习速率非常慢的情况。其偏导值在输出概率值接近0或者接近1的时候非常小,这可能会造成模型刚开始训练时,偏导值几乎消失。而使用交叉熵作为损失函数则不会导致这样的情况发生。
交叉熵:在二分的情况下,模型最后需要预测的结果只有两种情况,对于每个类别我们的预测得到的概率为p 和1-p 。此时表达式为:
y代表样本的label,p代表预测成功的概率。概率是什么看下面例子
多分类的情况实际上就是对二分类的扩展:
M为类别的数量?y为指示变量(0或1),如果该类别和样本i的类别相同就是1,否则是0;p为对于观测样本i属于类别 c 的预测概率。
当然越小越好。
此外,由于交叉熵涉及到计算每个类别的概率,所以交叉熵几乎每次都和sigmoid(或softmax)函数一起出现。
我们用神经网络最后一层输出的情况,来看一眼整个模型预测、获得损失和学习的流程:
- 神经网络最后一层得到每个类别的得分scores;
- 该得分经过sigmoid(或softmax)函数获得概率输出;
- 模型预测的类别概率输出与真实类别的one hot形式进行交叉熵损失函数的计算。
sigmoid(softmax)+cross-entropy loss 擅长于学习类间的信息,因为它采用了类间竞争机制,它只关心对于正确标签预测概率的准确性,忽略了其他非正确标签的差异,导致学习到的特征比较散。基于这个问题的优化有很多,比如对softmax进行改进,如L-Softmax、SM-Softmax、AM-Softmax等。
好了,现在看看有关tensorflow的问题
tensorflow的占位符本质就是先声明数据类型,以便建立模型时申请内存。怎么说呢,就是声明一下数据类型,毕竟python传过数据的时候不像C语言那样定义好了早就。建立一个空的架子,就像很多个有关节的管道。然后等你的数据进来,不断地优化这个管道,有的节点被砍掉,有的被变粗。所以tensorflow其实就是tensor的流动。tensor可以理解为多维数据。
tf.placeholder并且有三个参数
(1)数据类型
(2)数据大小
(3)占位符名称
-
x = tf.placeholder(tf.float32, [2, 50], name = 'originalx')
-
y = tf.placeholder(tf.float32, [2,50], name = 'originaly')
唉,这就是python不能声明的问题。
这个只是一个前向的说明,完全符合之前的图像。
什么是泄露relu呢,就是在负数上不是永远是0,而是一个极小负数,它的好处是什么呢,就是不会梯度消失,总会有一个数。使得负轴的信息不会全部丢失。
用python还有一个缺点是什么,就是变量不能封装,而且神经网络往往参数巨多,那么就用tf一套封装机制来设计。嗯。
z就像一个起始值,又像一个噪音,反正不管怎么说吧,它应该是一个随机数,作为初始扰动,确保生成的图像不是一样的,而是随机的。
鉴别器网络与发生器网络几乎完全相同,那你现在就是感觉它的误差回归比较难了?
训练这样的两个模型的大方法就是:单独交替迭代训练。什么意思?因为是2个网络,不好一起训练,所以才去交替迭代训练,我们一一来看。
首先这里有一个生成器,还有一个真数据集,生成器生成的数据的标签是0,真数据集的标签是1
然后接下来是判别器,将真假数据集送往判别器,哎,这里根据标签进行反向传播,修改自身参数,使自己能够更加判别出来。这样判别器就训练了一遍。
然后呢?就是训练生成器,因为判别器经过判断,有些假数据被判别为假,有些假数据被判别为真,然后这就有误差了,生成器于是就用都是1来反向传播这些假数据,这样生成器就可以训练了。
什么时候停止呢?循环个几万次停止就好了,或者说,当判别器几乎都输出1的时候,差不多就好了。
大概明白啥意思了。