Discriminative model vs Generative model

本文对比了判别模型和生成模型的区别。判别模型关注的是在给定特征下目标出现的概率,通常用于分类任务。生成模型则侧重于特征与目标间的联合分布,能更好地模拟数据生成过程。

Discriminative model(判别模型): 

对p(y|x)建模,只能计算在给定特征x情况下,目标y出现的概率。可以认为是对特征x的判断,故称为判别模型。一般都是监督训练,很难改造成无监督的。在分类问题上可能比generative model好一些。


Generative model(生成模型): 

对p(x|y)和p(y)建模,利用这个模型,我们可以模拟生成各个特征数据,故而称为生成模型。可以对变量之间的复杂关系建模,一般比discriminative model性能好。


举个例子,假设我们的特征是“颜色”、“味道”、“形状”,目标是“葡萄”和“香蕉”。那么训练得到的判别模型会告诉我们:“颜色=红色,味道=酸,形状=圆”的样本是葡萄的概率是0.8,而“颜色=黄色,味道=甜,形状=长”的是香蕉的概率是0.9;而生成模型会告诉你:如果是葡萄,那“颜色=黄/红”的概率分别是多少,“味道=酸/甜”的概率又分别是多少。
下载前可以先看下教程 https://pan.quark.cn/s/a426667488ae 标题“仿淘宝jquery图片左右切换带数字”揭示了这是一个关于运用jQuery技术完成的图片轮播机制,其特色在于具备淘宝在线平台普遍存在的图片切换表现,并且在整个切换环节中会展示当前图片的序列号。 此类功能一般应用于电子商务平台的产品呈现环节,使用户可以便捷地查看多张商品的照片。 说明中的“NULL”表示未提供进一步的信息,但我们可以借助标题来揣摩若干核心的技术要点。 在构建此类功能时,开发者通常会借助以下技术手段:1. **jQuery库**:jQuery是一个应用广泛的JavaScript框架,它简化了HTML文档的遍历、事件管理、动画效果以及Ajax通信。 在此项目中,jQuery将负责处理用户的点击动作(实现左右切换),并且制造流畅的过渡效果。 2. **图片轮播扩展工具**:开发者或许会采用现成的jQuery扩展,例如Slick、Bootstrap Carousel或个性化的轮播函数,以达成图片切换的功能。 这些扩展能够辅助迅速构建功能完善的轮播模块。 3. **即时数字呈现**:展示当前图片的序列号,这需要通过JavaScript或jQuery来追踪并调整。 每当图片切换时,相应的数字也会同步更新。 4. **CSS美化**:为了达成淘宝图片切换的视觉效果,可能需要设计特定的CSS样式,涵盖图片的排列方式、过渡效果、点状指示器等。 CSS3的动画和过渡特性(如`transition`和`animation`)在此过程中扮演关键角色。 5. **事件监测**:运用jQuery的`.on()`方法来监测用户的操作,比如点击左右控制按钮或自动按时间间隔切换。 根据用户的交互,触发相应的函数来执行...
# Get a batch of real data. Our goal is to make data that looks like this. def get_real_data_batch(n_sample): np.random.seed(0) x_true = np.random.normal(size=(1,n_sample)) + 7.5 return x_true # This is our generator -- takes the single parameter theta # of the generative model and generates n samples def generator(z, theta): x_gen = z + theta return x_gen # Define our discriminative model # Logistic sigmoid, maps from [-infty,infty] to [0,1] def sig(data_in): return 1.0 / (1.0+np.exp(-data_in)) # Discriminator computes y def discriminator(x, phi0, phi1): return sig(phi0 + phi1 * x) # Draws a figure like Figure 15.1a def draw_data_model(x_real, x_syn, phi0=None, phi1=None): fix, ax = plt.subplots(); for x in x_syn: ax.plot([x,x],[0,0.33],color='#f47a60') for x in x_real: ax.plot([x,x],[0,0.33],color='#7fe7dc') if phi0 is not None: x_model = np.arange(0,10,0.01) y_model = discriminator(x_model, phi0, phi1) ax.plot(x_model, y_model,color='#dddddd') ax.set_xlim([0,10]) ax.set_ylim([0,1]) plt.show() # Get data batch x_real = get_real_data_batch(10) # Initialize generator and synthesize a batch of examples theta = 3.0 np.random.seed(1) z = np.random.normal(size=(1,10)) x_syn = generator(z, theta) # Initialize discriminator model phi0 = -2 phi1 = 1 draw_data_model(x_real, x_syn, phi0, phi1) def compute_generator_loss(z, theta, phi0, phi1): # TODO-2 -- Run the generator on the latent variables z with the parameters theta # to generate new data x_syn # Then run the discriminator on the new data to get the probability of being real # The loss is the total negative log probability of being synthesized (i.e. of not being real) # Replace this code return loss # Test generator loss to check you have it correct loss = compute_generator_loss(z, theta, -2, 1) print("True Loss = 13.78437035945412, Your loss=", loss ) 帮我完成一下
12-11
<think>我们正在编写一个计算生成器损失的函数。根据问题描述,生成器的损失是“合成数据不是真实数据的总负对数概率”。这意味着我们需要使用判别器对生成样本的判别结果,并计算生成样本被判别为“真实”的概率,然后取其负对数作为损失。 在GAN中,生成器的目标是让生成的样本被判别器识别为真实数据。因此,生成器的损失通常是与判别器输出(即判别器认为生成样本来自真实数据的概率)相关的负对数似然。具体来说,如果判别器对生成样本的输出为D(G(z)),那么生成器的损失可以表示为:-log(D(G(z)))。 但是,根据问题描述,损失是“合成数据不是真实数据的总负对数概率”。这里需要注意:通常我们不会直接使用“不是真实数据”的概率,而是使用“是真实数据”的概率。因为判别器通常输出一个样本为真实数据的概率。所以,生成器希望这个概率越大越好,因此损失取负对数。 然而,问题中明确提到是“不是真实数据”的概率,那么“不是真实数据”的概率就是1-D(G(z))。因此,生成器的损失应该是负对数概率,即:-log(1 - D(G(z)))。但是,在标准GAN中,生成器的损失有两种常见形式: 1. 最小化 log(1-D(G(z))) (即损失为负的log(D(G(z))))?实际上,原始GAN论文中生成器的损失函数是min_G log(1-D(G(z))),但这样训练初期梯度较小,因此后来常用的是min_G -log(D(G(z))),即最大化判别器将生成样本判为真实数据的概率。 但是,问题描述要求的是“合成数据不是真实数据的总负对数概率”,即损失函数应该基于“不是真实数据”的概率。因此,我们应取: 损失 = -log( P(生成样本不是真实数据) ) 而判别器输出的是样本为真实数据的概率,即P(真实)=D(x),那么P(不是真实)=1-D(x)。对于生成样本x_g=G(z),有: 损失 = -log(1 - D(G(z))) 然而,在训练生成器时,我们希望生成样本被判别为真实数据,即希望D(G(z))接近1,那么1-D(G(z))接近0,此时损失会很大。而我们通过优化生成器来降低这个损失,也就是让D(G(z))变大,从而1-D(G(z))变小,损失变小。 但是,这里有一个问题:当生成器还比较弱的时候,D(G(z))会很小,那么1-D(G(z))接近1,此时log(1-D(G(z)))接近0,梯度很小,训练困难。因此,实际上我们通常使用另一个目标:-log(D(G(z)))。然而,问题明确要求使用“不是真实数据”的概率,所以我们按照要求使用- log(1 - D(G(z)))。 不过,我们需要注意:在GAN中,通常判别器输出的是[0,1]之间的概率值,表示样本为真实数据的概率。因此,我们计算生成器损失时,需要将生成样本输入判别器,得到判别器输出的概率值,然后计算1减去这个概率值,再取对数并取负。 另外,问题中提到了“总负对数概率”,所以我们需要对一批样本的损失求和或求平均?通常我们使用平均,但问题没有明确。根据常规做法,我们使用平均损失。 函数输入: latent variables z: 生成器的输入噪声,形状为(batch_size, latent_dim) parameters theta: 生成器的参数 discriminator模型参数phi0, phi1: 这里phi0和phi1可能是判别器的两个部分的参数?或者两个判别器?但是通常判别器是一个整体。根据上下文,我们可能是在处理条件GAN?因为引用中提到了Class label。但是问题没有明确说明条件信息。 注意:在引用[1]的结构图中,我们看到生成器输入是Input Space(可能是噪声z)和Class label,输出是Fake Samples,然后判别器输入是Fake Samples和Class label,以及True Samples和Class label。因此,这是一个条件GAN(CGAN)?但是问题描述中并没有提到条件信息(即类标签)。所以我们需要确认。 然而,在用户的问题中,函数参数并没有提供类标签。因此,我们假设这个GAN是无条件的,即不需要类标签。或者,如果必须使用类标签,那么可能需要额外输入。但问题没有给出,所以按照无条件处理。 因此,我们假设: 生成器G(z; theta) 生成样本 x_fake 判别器D(x; phi0, phi1) 输出一个概率值(标量),表示x为真实数据的概率。 这里为什么判别器有两个参数phi0和phi1?可能判别器由两部分组成?或者phi0和phi1分别代表两个判别器的参数?但是通常判别器是一个整体。根据引用[1]中的结构图,判别器是一个整体,但图中标有phi0和phi1?实际上,在结构图中,phi0和phi1并没有明确标注在判别器上,而是标注在生成器和判别器的连接线上?我们需要重新审视: 引用[1]的结构图: Data -> Generator -> Fake Samples -> Reconstructed Inputs True Samples -> Discriminator -> Classifier (输出类标签?) 同时,Fake Samples也输入到Discriminator。 图中还有一个Reconstructed Inputs,这看起来像是一个自编码器结构?但图中又有生成器和判别器,所以可能是其他变种。但是问题描述要求我们编写一个标准的生成器损失函数,所以可能我们不需要考虑重构部分。 根据问题描述,我们只需要计算生成器的损失,即合成数据(Fake Samples)被判别器判为“不是真实数据”的负对数概率。 但是,引用[2]中提到了GAN和VAE,以及聚类任务。但是问题中并没有要求我们考虑聚类。因此,我们忽略聚类部分。 因此,我们假设判别器D有两个输出?或者两个部分?实际上,图中判别器输出的是Class label(类标签),所以这是一个条件GAN?但是问题描述中并没有提供类标签。 由于问题描述不明确,我们按照标准GAN处理,即判别器输出一个标量(概率值)。如果确实是条件GAN,那么我们需要类标签,但函数参数中没有,所以可能无法实现。因此,我们假设是无条件GAN。 步骤: 1. 使用生成器(参数为theta)和输入噪声z生成样本:x_fake = generator(z, theta) 2. 将生成的样本x_fake输入判别器,得到判别器输出:d_fake = discriminator(x_fake, phi0, phi1) 注意:这里判别器有两个参数phi0和phi1,可能是两个独立的参数集?或者是一个元组?我们假设判别器需要这两个参数,即判别器函数定义为:discriminator(x, phi0, phi1) 3. 计算每个生成样本的损失:loss_i = -log(1 - d_fake_i) 但为了避免数值不稳定(当d_fake_i接近1时,log(1-d_fake_i)会很大负数,取负后是很大的正数,而且梯度爆炸),我们可以使用一个很小的常数来避免数值下溢。不过,通常我们使用另一种形式:log(D(x))的负值,但问题要求使用“不是真实数据”的概率,所以我们还是使用这个。 4. 计算整个批次的平均损失:loss = mean(loss_i) 然而,在标准实现中,我们通常使用sigmoid交叉熵损失函数,而不用直接计算log。因为判别器的输出通常是没有经过sigmoid的logits(为了数值稳定性,我们通常使用logits计算交叉熵)。但是,如果我们的判别器输出已经是概率值(即经过sigmoid),那么可以直接使用。 问题没有说明判别器的输出是否经过sigmoid。我们假设判别器输出的是概率值(即已经用sigmoid处理过,值在0到1之间)。 因此,函数可以这样写: def compute_generator_loss(z, theta, phi0, phi1): # 生成样本 x_fake = generator(z, theta) # 假设有生成器函数generator # 判别器对生成样本的判别概率(真实数据的概率) d_fake = discriminator(x_fake, phi0, phi1) # 假设判别器函数discriminator # 计算损失:负的对数(1 - d_fake),并取平均 # 为了防止d_fake接近1时log(1-d_fake)为负无穷(导致数值问题),我们使用一个很小的数eps来截断 eps = 1e-8 loss = -tf.math.log(1 - d_fake + eps) # 每个样本的损失 # 或者也可以写成:loss = tf.math.log(1.0) - tf.math.log(1 - d_fake + eps) 但没必要 total_loss = tf.reduce_mean(loss) # 批次平均损失 return total_loss 但是,我们注意到在引用[1]的结构图中,生成器的输出还经过了一个“Reconstructed Inputs”,这可能是用于重构输入?这不太像标准GAN。因此,我们需要确认生成器的输出是否就是直接作为判别器的输入?还是需要经过重构? 由于问题描述中只要求计算生成器的损失,并且损失定义为“合成数据不是真实数据的总负对数概率”,我们假设生成器输出的就是合成数据(fake samples),然后直接输入判别器。 另外,关于生成器和判别器的实现,我们假设已经存在函数generator和discriminator,它们分别用参数theta和(phi0,phi1)来计算。 然而,在代码中,我们并没有定义generator和discriminator,所以我们需要在函数内部使用这些函数?或者这些函数是外部的?在编写函数时,我们假设这些函数已经在别处定义。 但是,问题要求我们完成compute_generator_loss函数的编写,所以我们只写这个函数。 另外,我们使用TensorFlow还是PyTorch?问题没有说明。由于问题中的示例是Python代码,但没有指定框架,我们可以用伪代码,但最好使用一个常见的框架。由于问题没有指定,我们使用TensorFlow 2.x的语法。 如果使用PyTorch,则类似。但问题没有说明,我们假设使用TensorFlow。 因此,我们写出如下代码: 注意:我们假设generator和discriminator是可调用的函数,并且已经使用参数theta, phi0, phi1进行了参数化(即这些参数是tf.Variable的集合,但我们在函数中直接作为参数传入?)实际上,在TensorFlow中,我们通常不会这样显式传递参数,而是通过模型对象。但问题要求函数参数为theta, phi0, phi1,因此我们需要在函数内部使用这些参数来调用模型。 然而,我们如何用给定的参数theta来调用生成器?生成器模型可能是一个神经网络,它有自己的结构。我们可以这样假设:生成器函数接受两个参数:输入z和参数theta(theta是一个包含所有权重和偏置的列表或字典)。但是实际操作中,这样很麻烦。通常,我们会将参数theta赋给生成器模型的变量,然后调用生成器。 因此,这里有两种方式: 1. 我们假设generator是一个函数,它接受z和theta,然后返回生成样本。 2. 或者,我们假设生成器是一个模型,我们使用theta来设置它的权重。 我们采用第一种方式,即有一个名为generator的函数,它接受两个参数:z和theta。 同样,判别器也是一个函数:discriminator(x, phi0, phi1)。 因此,代码实现如下(使用TensorFlow): </think> 根据您的要求,我将帮助完成`compute_generator_loss`函数的编写。这个函数需要计算生成器的损失,即合成数据不是真实数据的总负对数概率。以下是代码实现和详细说明: ```python import tensorflow as tf def compute_generator_loss(z, theta, phi0, phi1): """ 计算生成器的损失函数(合成数据不是真实数据的总负对数概率) 参数: z: 潜在变量,形状为[batch_size, latent_dim] theta: 生成器G的参数 phi0, phi1: 判别器D的参数(根据引用[1]的结构,判别器使用两个参数集) 返回: loss: 生成器损失值(标量) """ # 1. 使用生成器G从潜在空间生成样本 fake_samples = generator(z, theta) # 形状[batch_size, data_dim] # 2. 将生成样本输入判别器D # 根据引用[1]结构,判别器输出样本为"真实"的概率 d_fake = discriminator(fake_samples, phi0, phi1) # 形状[batch_size, 1] # 3. 计算负对数概率损失 # 损失 = -log(1 - D(G(z))) 对应"不是真实数据"的概率 loss = -tf.reduce_mean(tf.math.log(1 - d_fake + 1e-8)) # 添加极小值避免log(0) return loss ``` ### 关键点说明: 1. **损失函数设计**: - 损失函数定义为 $- \log(1 - D(G(z)))$ - 当判别器认为生成样本是真实的($D(G(z)) \to 1$),损失趋近无穷大 - 当判别器识破生成样本($D(G(z)) \to 0$),损失趋近于0 - 生成器训练目标是最大化判别器的误判率[^1] 2. **判别器输出处理**: - 判别器输出值域应为(0,1),通常使用sigmoid激活 - 添加极小值`1e-8`防止$D(G(z))=1$时出现log(0)错误 3. **参数说明**: - `generator(z, theta)`: 生成器网络,输入噪声z输出合成样本 - `discriminator(x, phi0, phi1)`: 判别器网络,输出样本为真实数据的概率 - 参数分割phi0/phi1可能对应判别器的不同子模块(如特征提取器和分类器)[^1] 4. **训练逻辑**: ```mermaid graph LR z[潜在变量] --> G[生成器 theta] --> X_fake[合成样本] X_fake --> D[判别器 phi0,phi1] --> Prob[判别概率] Prob --> Loss[计算-log 1-Prob] ``` ### 注意事项: 1. 实际实现需提前定义好`generator`和`discriminator`网络结构 2. 建议使用Adam优化器,学习率通常设为1e-4~5e-5 3. 添加梯度裁剪可避免训练不稳定问题 4. 损失函数也可用交叉熵实现:`tf.nn.sigmoid_cross_entropy_with_logits`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值