Jos*_*mon 13 python conv-neural-network keras loss-function generative-adversarial-network
我试图找出如何使用Generative Adversarial Networks的数据集标签信息.我试图使用可在此处找到的条件GAN的以下实现.我的数据集包含两个不同的图像域(真实对象和草图),具有公共类信息(椅子,树,橙等).我选择了这种实现,它只将两个不同的域视为对应的不同"类"(列车样本X对应于真实图像,而目标样本y对应于草图图像).
有没有办法修改我的代码并考虑我整个架构中的类信息(椅子,树等)?我希望我的鉴别器能够预测我生成的图像来自生成器是否属于特定类,而不仅仅是它们是否真实.实际上,在当前架构中,系统学会在所有情况下创建类似的草图.
更新:鉴别器返回一个大小的张量1x7x7然后两者y_true并y_pred在计算损失之前通过展平层:
def discriminator_loss(y_true, y_pred):
BATCH_SIZE=100
return K.mean(K.binary_crossentropy(K.flatten(y_pred), K.concatenate([K.ones_like(K.flatten(y_pred[:BATCH_SIZE,:,:,:])),K.zeros_like(K.flatten(y_pred[:BATCH_SIZE,:,:,:])) ]) ), axis=-1)
Run Code Online (Sandbox Code Playgroud)
以及鉴别器对发电机的损失功能:
def discriminator_on_generator_loss(y_true,y_pred):
BATCH_SIZE=100
return K.mean(K.binary_crossentropy(K.flatten(y_pred), K.ones_like(K.flatten(y_pred))), axis=-1)
Run Code Online (Sandbox Code Playgroud)
此外,我对输出1层的鉴别器模型的修改:
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
#model.add(Activation('sigmoid'))
Run Code Online (Sandbox Code Playgroud)
现在鉴别器输出1层.如何相应修改上述损失函数?我应该有7而不是1,n_classes = 6用于预测真实和假对的+一类吗?
重用您共享的存储库中的代码,以下是一些建议的修改,以便在您的生成器和鉴别器上训练分类器(它们的架构和其他损失保持不变):
from keras import backend as K
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
def lenet_classifier_model(nb_classes):
# Snipped by Fabien Tanc - https://www.kaggle.com/ftence/keras-cnn-inspired-by-lenet-5
# Replace with your favorite classifier...
model = Sequential()
model.add(Convolution2D(12, 5, 5, activation='relu', input_shape=in_shape, init='he_normal'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(25, 5, 5, activation='relu', init='he_normal'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(180, activation='relu', init='he_normal'))
model.add(Dropout(0.5))
model.add(Dense(100, activation='relu', init='he_normal'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes, activation='softmax', init='he_normal'))
def generator_containing_discriminator_and_classifier(generator, discriminator, classifier):
inputs = Input((IN_CH, img_cols, img_rows))
x_generator = generator(inputs)
merged = merge([inputs, x_generator], mode='concat', concat_axis=1)
discriminator.trainable = False
x_discriminator = discriminator(merged)
classifier.trainable = False
x_classifier = classifier(x_generator)
model = Model(input=inputs, output=[x_generator, x_discriminator, x_classifier])
return model
def train(BATCH_SIZE):
(X_train, Y_train, LABEL_train) = get_data('train') # replace with your data here
X_train = (X_train.astype(np.float32) - 127.5) / 127.5
Y_train = (Y_train.astype(np.float32) - 127.5) / 127.5
discriminator = discriminator_model()
generator = generator_model()
classifier = lenet_classifier_model(6)
generator.summary()
discriminator_and_classifier_on_generator = generator_containing_discriminator_and_classifier(
generator, discriminator, classifier)
d_optim = Adagrad(lr=0.005)
g_optim = Adagrad(lr=0.005)
generator.compile(loss='mse', optimizer="rmsprop")
discriminator_and_classifier_on_generator.compile(
loss=[generator_l1_loss, discriminator_on_generator_loss, "categorical_crossentropy"],
optimizer="rmsprop")
discriminator.trainable = True
discriminator.compile(loss=discriminator_loss, optimizer="rmsprop")
classifier.trainable = True
classifier.compile(loss="categorical_crossentropy", optimizer="rmsprop")
for epoch in range(100):
print("Epoch is", epoch)
print("Number of batches", int(X_train.shape[0] / BATCH_SIZE))
for index in range(int(X_train.shape[0] / BATCH_SIZE)):
image_batch = Y_train[index * BATCH_SIZE:(index + 1) * BATCH_SIZE]
label_batch = LABEL_train[index * BATCH_SIZE:(index + 1) * BATCH_SIZE] # replace with your data here
generated_images = generator.predict(X_train[index * BATCH_SIZE:(index + 1) * BATCH_SIZE])
if index % 20 == 0:
image = combine_images(generated_images)
image = image * 127.5 + 127.5
image = np.swapaxes(image, 0, 2)
cv2.imwrite(str(epoch) + "_" + str(index) + ".png", image)
# Image.fromarray(image.astype(np.uint8)).save(str(epoch)+"_"+str(index)+".png")
# Training D:
real_pairs = np.concatenate((X_train[index * BATCH_SIZE:(index + 1) * BATCH_SIZE, :, :, :], image_batch),
axis=1)
fake_pairs = np.concatenate(
(X_train[index * BATCH_SIZE:(index + 1) * BATCH_SIZE, :, :, :], generated_images), axis=1)
X = np.concatenate((real_pairs, fake_pairs))
y = np.zeros((20, 1, 64, 64)) # [1] * BATCH_SIZE + [0] * BATCH_SIZE
d_loss = discriminator.train_on_batch(X, y)
print("batch %d d_loss : %f" % (index, d_loss))
discriminator.trainable = False
# Training C:
c_loss = classifier.train_on_batch(image_batch, label_batch)
print("batch %d c_loss : %f" % (index, c_loss))
classifier.trainable = False
# Train G:
g_loss = discriminator_and_classifier_on_generator.train_on_batch(
X_train[index * BATCH_SIZE:(index + 1) * BATCH_SIZE, :, :, :],
[image_batch, np.ones((10, 1, 64, 64)), label_batch])
discriminator.trainable = True
classifier.trainable = True
print("batch %d g_loss : %f" % (index, g_loss[1]))
if index % 20 == 0:
generator.save_weights('generator', True)
discriminator.save_weights('discriminator', True)
Run Code Online (Sandbox Code Playgroud)
我认为对于有条件的GAN如何运作以及这些方案中的歧视者角色存在一些误解.
在GAN训练的最小 - 最大游戏[4]中,鉴别D器正在与发生器G(你实际关心的网络)进行对抗,这样在经过D仔细检查后,G就能更好地输出真实的结果.
为此,D训练分开来自样本的真实样本G; 而G被训练来欺骗D通过产生以下的目标分布现实的结果/结果.
注意:在条件GAN的情况下,即GAN将输入样本从一个域
A(例如实际图片)映射到另一个域B(例如草图),D通常将堆叠在一起的样本对提供,并且必须区分"真实"对(来自A+对应目标样本的输入样本B和"假"对(来自A+对应输出的输入样本G) [1,2]
训练条件生成器D(而不是单纯训练G,只有L1/L2丢失,例如DAE)提高了采样能力G,迫使它输出清晰,逼真的结果,而不是试图平均分布.
尽管鉴别器可以有多个子网络来覆盖其他任务(参见下面的段落),但D应保留至少一个子网络/输出来覆盖其主要任务:分别从生成的样本中分析实际样本.要求D进一步回归进一步的语义信息(例如类)可能会干扰这个主要目的.
注意:
D输出通常不是简单的标量/布尔值.通常有一个鉴别器(例如PatchGAN [1,2])返回一个概率矩阵,评估从其输入得到的真实补丁是多少.
以无人监督的方式训练传统GAN以从随机噪声矢量作为输入生成真实数据(例如图像).[4]
如前所述,条件GAN具有进一步的输入条件.沿着/代替噪声向量,它们从域中输入样本并从域A返回相应的样本B.A可以是完全不同的模态,例如B = sketch image同时A = discrete label; B = volumetric data同时A = RGB image,等[3]
这样的GAN也可以由多个输入来调节,例如A = real image + discrete labelwhile B = sketch image.介绍这些方法的着名工作是InfoGAN [5].它提出了如何在多个连续或离散输入(例如调节甘斯A = digit class + writing type,B = handwritten digit image),使用具有用于第二任务强制更先进的鉴别器G以最大化其调节输入和其相应的输出之间的互信息.
InfoGAN鉴别器有2个头/子网络来完成它的2个任务[5]:
D1做传统的真实/产生的歧视 - G必须最小化这个结果,即它必须愚弄,D1以便它不能分辨真实形式生成的数据;D2(也称为Q网络)试图回归输入A信息 - G必须最大化该结果,即它必须输出"显示"所请求的语义信息的数据(参见G条件输入及其输出之间的互信息最大化).您可以在此处找到Keras实现,例如:https://github.com/eriklindernoren/Keras-GAN/tree/master/infogan.
通过使用提供的标签并最大化这些输入和G输出之间的互信息,一些工作正在使用类似的方案来改进对GAN生成的控制[6,7].基本思路总是一样的:
G在B给出域的一些输入的情况下,训练生成域的元素A;D歧视"真实"/"假"结果 - G必须尽量减少这种情况;Q(例如分类器;可以共享层D)以估计样本的原始A输入B- G必须最大化这个).在您的情况下,您似乎有以下培训数据:
IaIbc并且您希望训练一个生成器,G以便给定一个图像Ia及其类标签c,它会输出一个合适的草图图像Ib'.
总而言之,这是你拥有的大量信息,你可以监控你在条件图像和条件标签上的训练......灵感来自前面提到的方法[1,2,5,6,7],这里是一个使用所有这些信息来训练您的条件的可能方式G:
G:
Ia+cIb'Ib'&之间的L1/L2损失Ib,-D损失,Q损失D:
Ia+ Ib(真实对),Ia+ Ib'(假对)Q:
Ib真实样本,用于训练Q),Ib'(假样本,反向传播时G)c'估计等级)c和之间的交叉熵c'D一批真正的对Ia+ Ib然后是一批假对Ia+ Ib';Q一批真实样本Ib;D和Q重量;G,将生成的输出传递Ib'给它们D并Q通过它们反向传播.注意:这是一个非常粗略的架构描述.我建议通过文献([1,5,6,7]作为一个良好的开端)来获得更多细节,也许是一个更精细的解决方案.
| 归档时间: |
|
| 查看次数: |
559 次 |
| 最近记录: |