对抗思想与强化学习的碰撞-SeqGAN模型原理和代码解析

GAN作为生成模型的一种新型训练方法,通过discriminative model来指导generative model的训练,并在真实数据中取得了很好的效果。尽管如此,当目标是一个待生成的非连续性序列时,该方法就会表现出其局限性。非连续性序列生成,比如说文本生成,为什么单纯的使用GAN没有取得很好的效果呢?主要的屏障有两点:
1)在GAN中,Generator是通过随机抽样作为开始,然后根据模型的参数进行确定性的转化。通过generative model G的输出,discriminative model D计算的损失值,根据得到的损失梯度去指导generative model G做轻微改变,从而使G产生更加真实的数据。而在文本生成任务中,G通常使用的是LSTM,那么G传递给D的是一堆离散值序列,即每一个LSTM单元的输出经过softmax之后再取argmax或者基于概率采样得到一个具体的单词,那么这使得梯度下架很难处理

2)GAN只能评估出整个生成序列的score/loss,不能够细化到去评估当前生成token的好坏和对后面生成的影响

强化学习可以很好的解决上述的两点。再回想一下Policy Gradient的基本思想,即通过reward作为反馈,增加得到reward大的动作出现的概率,减小reward小的动作出现的概率,如果我们有了reward,就可以进行梯度训练,更新参数。如果使用Policy Gradient的算法,当G产生一个单词时,如果我们能够得到一个反馈的Reward,就能通过这个reward来更新G的参数,而不再需要依赖于D的反向传播来更新参数,因此较好的解决了上面所说的第一个屏障。对于第二个屏障,当产生一个单词时,我们可以使用蒙塔卡罗树搜索(Alpho Go也运用了此方法)立即评估当前单词的好坏,而不需要等到整个序列结束再来评价这个单词的好坏。

因此,强化学习和对抗思想的结合,理论上可以解决非连续序列生成的问题,而SeqGAN模型,正是这两种思想碰撞而产生的可用于文本序列生成的模型。

SeqGAN模型的原文地址为:https://arxiv.org/abs/1609.05473,当然在我的github链接中已经把下载好的原文贴进去啦。

结合代码可以更好的理解模型的细节哟:https://github.com/princewen/tensorflow_practice/tree/master/seqgan

2、SeqGAN的原理

SeqGAN的全称是Sequence Generative Adversarial Nets。这里打公式太麻烦了,所以我们用word打好再粘过来,冲这波手打也要给小编一个赞呀,哈哈!

整体流程

模型的示意图如下:

Generator模型和训练
接下来,我们分别来说一下Generator模型和Discriminator模型结构。

Generator一般选择的是循环神经网络结构,RNN,LSTM或者是GRU都可以。对于输入的序列,我们首先得到序列中单词的embedding,然后输入每个cell中,并结合一层全链接隐藏层得到输出每个单词的概率,即:

有了这个概率,Generator可以根据它采样一批产生的序列,比如我们生成一个只有,两个单词的序列,总共的单词序列有3个,第一个cell的输出为(0.5,0.5,0.0),第二个cell的输出为(0.1,0.8,0.1),那么Generator产生的序列以0.4的概率是1->2,以0.05的概率是1->1。注意这里Generator产生的序列是概率采样得到的,而不是对每个输出进行argmax得到的固定的值。这和policy gradient的思想是一致的。

在每一个cell我们都能得到一个概率分布,我们基于它选择了一个动作或者说一个单词,如何判定基于这个概率分布得到的单词的还是坏的呢?即我们需要一个reward来左右这个单词被选择的概率。这个reward怎么得到呢,就需要我们的Discriminator以及蒙塔卡罗树搜索方法了。前面提到过Reward的计算依据是最大可能的Discriminator,即尽可能的让Discriminator认为Generator产生的数据为real-world的数据。这里我们设定real-world的数据的label为1,而Generator产生的数据label为0.

如果当前的cell是最后的一个cell,即我们已经得到了一个完整的序列,那么此时很好办,直接把这个序列扔给Discriminator,得到输出为1的概率就可以得到reward值。如果当前的cell不是最后一个cell,即当前的单词不是最后的单词,我们还没有得到一个完整的序列,如何估计当前这个单词的reward呢?我们用到了蒙特卡罗树搜索的方法。即使用前面已经产生的序列,从当前位置的下一个位置开始采样,得到一堆完整的序列。在原文中,采样策略被称为roll-out policy,这个策略也是通过一个神经网络实现,这个神经网络我们可以认为就是我们的Generator。得到采样的序列后,我们把这一堆序列扔给Discriminator,得到一批输出为1的概率,这堆概率的平均值即我们的reward。这部分正如过程示意图中的下面一部分:

用原文中的公式表示如下:

得到了reward,我们训练Generator的方式就很简单了,即通过Policy Gradient的方式进行训练。最简单的思想就是增加reward大的动作的选择概率,减小reward小的动作的选择概率。

Discriminator模型和训练
Discriminator模型即一个分类器,对文本分类的分类器很多,原文采用的是卷积神经网络。同时为了使模型的分类效果更好,在CNN的基础上增加了一个highway network。有关highway network的介绍参考博客:https://blog.csdn.net/l494926429/article/details/51737883,这里就不再细讲啦。

对于Discriminator来说,既然是一个分类器,输出的又是两个类别的概率值,我们很自然的想到使用类似逻辑回归的对数损失函数,没错,论文中也是使用对数损失来训练Discriminator的。

结合oracle模型
可以说,模型我们已经介绍完了,但是在实验部分,论文中引入了一个新的模型中,被称为oracle model。这里的oracle如何翻译,我还真的是不知道,总不能翻译为甲骨文吧。这个oracle model被用来生成真实的序列,可以认为这个model就是一个被训练完美的lstm模型,输出的序列都是real-world数据。论文中使用这个模型的原因有两点:首先是可以用来产生训练数据,另一点是可以用来评价我们Generator的真实表现。原文如下:

我们会在训练过程中不断通过上面的式子来评估我们的Generator与oracle model的相似性。

预训练过程
上面我们讲的其实是在对抗过程中Generator和Discriminator的训练过程,其实在进行对抗之前,我们的Generator和Discriminator都有一个预训练的过程,这能使我们的模型更快的收敛。

对于Generator来说,预训练和对抗过程中使用的损失函数是不一样的,在预训练过程中,Generator使用的是交叉熵损失函数,而在对抗过程中,我们使用的则是Policy Gradient中的损失函数,即对数损失*奖励值。

而对Discriminator来说,两个过程中的损失函数都是一样的,即我们前面介绍的对数损失函数。

SeqGAN模型流程

介绍了这么多,我们再来看一看SeqGAN的流程:

3、SeqGAN代码解析

这里我们用到的代码高度还原了原文中的实验过程,本文参考的github代码地址为:https://github.com/ChenChengKuan/SeqGAN_tensorflow

参考的代码为python2版本的,本文将其稍作修改,改成了python3版本的。其实主要就是print和pickle两个地方。本文代码的github地址为:https://github.com/princewen/tensorflow_practice/tree/master/seqgan

代码实在是太多了,我们这里只介绍一下代码结构,具体的代码细节大家可以参考github进行学习。

3.1 代码结构

本文的代码结构如下:

save:save文件夹下保存了我们的实验日志,eval_file是由Generator产生,用来评价Generator和oracle model相似性所产生的数据。real_data是由oracle model产生的real-world数据,generator_sample是由Generator产生的数据,target_params是oracle model的参数,我们直接用里面的参数还原oracle model。

configuration : 一些配置参数

dataloader.py: 产生训练数据,对于Generator来说,我们只在预训练中使用dataloader来得到训练数据,对Discriminator来说,在预训练和对抗过程中都要使用dataloader来得到训练数据。而在eval过程即进行Generator和oracle model相似性判定时,会用刀dataloader来产生数据。

discriminator.py:定义了我们的discriminator

generator.py :定义了我们的generator

rollout.py:计算reward时的采样过程

target_lstm.py:定义了我们的oracle model,这个文件不用管,复制过去就好,哈哈。

train.py : 定义了我们的训练过程,这是我们一会重点讲解的文件

utils.py : 定义了一些在训练过程中的通用过程。

下面,我们就来介绍一下每个文件。

3.2 dataloader

dataloader是我们的数据生成器。

它定义了两个类,一个时Generator的数据生成器,主要用于Generator的预训练以及计算Generator和Oracle model的相似性。另一个时Discriminator的数据生成器,主要用于Discriminator的训练。

3.3 generator

generator中定义了我们的Generator,代码结构如下:

build_input:定义了我们的预训练模型和对抗过程中需要输入的数据

build_pretrain_network : 定义了Generator的预训练过程中的网络结构,其实这个网络结构在预训练,对抗和采样的过程中是一样的,参数共享。预训练过程中定义的损失是交叉熵损失。

build_adversarial_network: 定义了Generator的对抗过程的网络结构,和预训练过程共享参数,因此你可以发现代码基本上是一样的,只不过在对抗过程中的损失函数是policy gradient的损失函数,即 -log(p(xi) * v(xi):

self.pgen_loss_adv = - tf.reduce_sum(tf.reduce_sum(tf.one_hot(tf.to_int32(tf.reshape(self.input_seqs_adv,[-1])),self.num_emb,on_value=1.0,off_value=0.0)* tf.log(tf.clip_by_value(tf.reshape(self.softmax_list_reshape,[-1,self.num_emb]),1e-20,1.0)),1) * tf.reshape(self.rewards,[-1]))

build_sample_network:定义了我们Generator采样得到生成序列过程的网络结构,与前两个网络参数是共享的。

那么这三个网络是如何使用的呢?pretrain_network就是用来预训练我们的Generator的,这个没有异议。然后在对抗时的每一个epoch,首先用sample_network得到一堆采样的序列samples,然后对采样序列的对每一个时点,使用roll-out-policy结合Discriminator得到reward值。最后,把这些samples和reward值喂给adversarial_network进行参数更新。

3.4 discriminator

discriminator的文件结构如下:

前面的linearhighway函数实现了highway network。

在Discriminator类中,我们采用CNN建立了Discriminator的网络结构,值得注意的是,我们这里采用的损失函数加入了正则项:

with tf.name_scope("output"):W = tf.Variable(tf.truncated_normal([num_filters_total,self.num_classes],stddev = 0.1),name="W")b = tf.Variable(tf.constant(0.1,shape=[self.num_classes]),name='b')self.l2_loss += tf.nn.l2_loss(W)self.l2_loss += tf.nn.l2_loss(b)self.scores = tf.nn.xw_plus_b(self.h_drop,W,b,name='scores') # batch * num_classesself.ypred_for_auc = tf.nn.softmax(self.scores)self.predictions = tf.argmax(self.scores,1,name='predictions')

with tf.name_scope(“loss”):
losses = tf.nn.softmax_cross_entropy_with_logits(logits=self.scores,labels=self.input_y)
# 损失函数中加入了正则项
self.loss = tf.reduce_mean(losses) + self.l2_reg_lambda + self.l2_loss

3.5 rollout

这个文件实现的通过rollout-policy得到一堆完整序列的过程,前面我们提到过了,rollout-policy实现需要一个神经网络,而我们这里用Generator当作这个神经网络,所以它与前面提到的三个Generator的网络的参数也是共享的。

另外需要注意的是,我们这里要得到每个序列每个时点的采样数据,因此需要进行两层循环:

假设我们传过来的序列长度是20,最后一个不需要进行采样,因为已经是完整的序列了。假设当前的step是5,那么0-4是不需要采样的,但我们需要把0-4位置的序列输入到网络中得到state。得到state之后,我们再经过一层循环得到5-19位的采样序列,然后将0-4位置的序列的和5-19位置的序列的进行拼接。

sample_rollout = tf.concat([sample_rollout_left,sample_rollout_right],axis=1)

3.6 utils

utils中定义了两个函数:

generate_samples函数用于调用Generator中的sample_network产生sample或者用于调用target-lstm中的sample_network产生real-world数据

target_loss函数用于计算Generator和oracle model的相似性。

3.7 train

终于改介绍我们的主要流程控制代码了,先深呼吸一口,准备开始!

定义dataloader以及网络

首先,我们获取了configuration中定义的参数,然后基于这些参数,我们得到了三个dataloader。

随后,我们定义了Generator和Discriminator,以及通过读文件来创建了我们的oracle model,在代码中叫target_lstm。

config_train = training_config()
config_gen = generator_config()
config_dis = discriminator_config()

np.random.seed(config_train.seed)

assert config_train.start_token == 0
gen_data_loader = Gen_Data_loader(config_gen.gen_batch_size)
likelihood_data_loader = Gen_Data_loader(config_gen.gen_batch_size)
dis_data_loader = Dis_dataloader(config_dis.dis_batch_size)

generator = Generator(config=config_gen)
generator.build()

rollout_gen = rollout(config=config_gen)

#Build target LSTM
target_params = pickle.load(open(‘save/target_params.pkl’,‘rb’),encoding=‘iso-8859-1’)
target_lstm = TARGET_LSTM(config=config_gen, params=target_params) # The oracle model

# Build discriminator
discriminator = Discriminator(config=config_dis)
discriminator.build_discriminator()

预训练Generator

我们首先定义了预训练过程中Generator的优化器,即通过AdamOptimizer来最小化交叉熵损失,随后我们通过target-lstm网络来产生Generator的训练数据,利用dataloader来读取每一个batch的数据。
同时,每隔一定的步数,我们会计算Generator与target-lstm的相似性(likelihood)

# Build optimizer op for pretraining
pretrained_optimizer = tf.train.AdamOptimizer(config_train.gen_learning_rate)
var_pretrained = [v for v in tf.trainable_variables() if 'teller' in v.name]
gradients, variables = zip(*pretrained_optimizer.compute_gradients(generator.pretrained_loss, var_list=var_pretrained))
gradients, _ = tf.clip_by_global_norm(gradients, config_train.grad_clip)
gen_pre_update = pretrained_optimizer.apply_gradients(zip(gradients, variables))

sess = tf.Session()
sess.run(tf.global_variables_initializer())

generate_samples(sess,target_lstm,config_train.batch_size,config_train.generated_num,config_train.positive_file)
gen_data_loader.create_batches(config_train.positive_file)

log = open(‘save/experiment-log.txt’,‘w’)
print(‘Start pre-training generator…’)

log.write(‘pre-training…\n’)

for epoch in range(config_train.pretrained_epoch_num):
gen_data_loader.reset_pointer()
for it in range(gen_data_loader.num_batch):
batch = gen_data_loader.next_batch()
_,g_loss = sess.run([gen_pre_update,generator.pretrained_loss],feed_dict={generator.input_seqs_pre:batch,
generator.input_seqs_mask:np.ones_like(batch)})

<span class="hljs-keyword">if</span> epoch % config_train.test_per_epoch == 0:<span class="hljs-comment">#进行测试,通过Generator产生一批序列,</span>generate_samples(sess,generator,config_train.batch_size,config_train.generated_num,config_train.eval_file)<span class="hljs-comment"># 创建这批序列的data-loader</span>likelihood_data_loader.create_batches(config_train.eval_file)<span class="hljs-comment"># 使用oracle 计算 交叉熵损失nll</span>test_loss = target_loss(sess,target_lstm,likelihood_data_loader)<span class="hljs-comment"># 打印并写入日志</span><span class="hljs-built_in">print</span>(<span class="hljs-string">'pre-train '</span>,epoch, <span class="hljs-string">' test_loss '</span>,test_loss)buffer = <span class="hljs-string">'epoch:\t'</span> + str(epoch) + <span class="hljs-string">'\tnll:\t'</span> + str(test_loss) + <span class="hljs-string">'\n'</span>log.write(buffer)

预训练Discriminator
预训练好Generator之后,我们就可以通过Generator得到一批负样本,并结合target-lstm产生的正样本来预训练我们的Discriminator。

print('Start pre-training discriminator...')
for t in range(config_train.dis_update_time_pre):print("Times: " + str(t))generate_samples(sess,generator,config_train.batch_size,config_train.generated_num,config_train.negative_file)dis_data_loader.load_train_data(config_train.positive_file,config_train.negative_file)for _ in range(config_train.dis_update_time_pre):dis_data_loader.reset_pointer()for it in range(dis_data_loader.num_batch):x_batch,y_batch = dis_data_loader.next_batch()feed_dict = {discriminator.input_x : x_batch,discriminator.input_y : y_batch,discriminator.dropout_keep_prob : config_dis.dis_dropout_keep_prob}_ = sess.run(discriminator.train_op,feed_dict)

定义对抗过程中Generator的优化器
这里定义的对抗过程中Generator的优化器即最小化我们前面提到的policy gradient损失,再回顾一遍:

self.pgen_loss_adv = - tf.reduce_sum(tf.reduce_sum(tf.one_hot(tf.to_int32(tf.reshape(self.input_seqs_adv,[-1])),self.num_emb,on_value=1.0,off_value=0.0)* tf.log(tf.clip_by_value(tf.reshape(self.softmax_list_reshape,[-1,self.num_emb]),1e-20,1.0)),1) * tf.reshape(self.rewards,[-1]))
# Build optimizer op for adversarial training
train_adv_opt = tf.train.AdamOptimizer(config_train.gen_learning_rate)
gradients, variables = zip(*train_adv_opt.compute_gradients(generator.gen_loss_adv, var_list=var_pretrained))
gradients, _ = tf.clip_by_global_norm(gradients, config_train.grad_clip)
train_adv_update = train_adv_opt.apply_gradients(zip(gradients, variables))

# Initialize global variables of optimizer for adversarial training
uninitialized_var = [e for e in tf.global_variables() if e not in tf.trainable_variables()]
init_vars_uninit_op = tf.variables_initializer(uninitialized_var)
sess.run(init_vars_uninit_op)

对抗过程中训练Generator
对抗过程中训练Generator,我们首先需要通过Generator得到一批序列sample,然后使用roll-out结合Dsicriminator得到每个序列中每个时点的reward,再将reward和sample喂给adversarial_network进行参数更新。

# Start adversarial training
for total_batch in range(config_train.total_batch):for iter_gen in range(config_train.gen_update_time):samples = sess.run(generator.sample_word_list_reshpae)
    feed = {<span class="hljs-string">'pred_seq_rollout:0'</span><span class="hljs-symbol">:samples</span>}reward_rollout = []<span class="hljs-keyword">for</span> iter_roll <span class="hljs-keyword">in</span> range(config_train.rollout_num):rollout_list = sess.run(rollout_gen.sample_rollout_step,feed_dict=feed)<span class="hljs-comment"># np.vstack 它是垂直(按照行顺序)的把数组给堆叠起来。</span>rollout_list_stack = np.vstack(rollout_list)reward_rollout_seq = sess.run(discriminator.ypred_for_auc,feed_dict={discriminator.<span class="hljs-symbol">input_x:</span>rollout_list_stack,discriminator.<span class="hljs-symbol">dropout_keep_prob:</span><span class="hljs-number">1.0</span>})reward_last_tok = sess.run(discriminator.ypred_for_auc,feed_dict={discriminator.<span class="hljs-symbol">input_x:</span>samples,discriminator.<span class="hljs-symbol">dropout_keep_prob:</span><span class="hljs-number">1.0</span>})reward_allseq = np.concatenate((reward_rollout_seq,reward_last_tok),axis=<span class="hljs-number">0</span>)[<span class="hljs-symbol">:</span>,<span class="hljs-number">1</span>]reward_tmp = []<span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> range(config_gen.gen_batch_size):reward_tmp.append(reward_allseq[range(r,config_gen.gen_batch_size * config_gen.sequence_length,config_gen.gen_batch_size)])reward_rollout.append(np.array(reward_tmp))rewards = np.sum(reward_rollout,axis = <span class="hljs-number">0</span>) / config_train.rollout_num<span class="hljs-number">_</span>,gen_loss = sess.run([train_adv_update,generator.gen_loss_adv],feed_dict={generator.<span class="hljs-symbol">input_seqs_adv:</span>samples,generator.<span class="hljs-symbol">rewards:</span>rewards})

对抗过程中训练Discriminator

对抗过程中Discriminator的训练和预训练过程一样,这里就不再赘述。

for _ in range(config_train.dis_update_time_adv):generate_samples(sess,generator,config_train.batch_size,config_train.generated_num,config_train.negative_file)dis_data_loader.load_train_data(config_train.positive_file,config_train.negative_file)
<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(config_train.dis_update_time_adv):dis_data_loader.reset_pointer()<span class="hljs-keyword">for</span> it <span class="hljs-keyword">in</span> range(dis_data_loader.num_batch):x_batch,y_batch = dis_data_loader.next_batch()feed = {discriminator.input_x:x_batch,discriminator.input_y:y_batch,discriminator.dropout_keep_prob:config_dis.dis_dropout_keep_prob}_ = sess.run(discriminator.train_op,feed)

3.8 训练效果

来一发训练效果截图:

可以看到,我们的Generator越来越接近oracle model啦,哈哈哈!

参考文献:

1、https://blog.csdn.net/liuyuemaicha/article/details/70161273
2、https://blog.csdn.net/yinruiyang94/article/details/77675586
3、https://www.jianshu.com/p/32e164883eab
4、https://blog.csdn.net/l494926429/article/details/51737883

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/481258.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如果你跟夕小瑶恋爱了...(下)

AB派在上一篇文章中&#xff0c;你成功的将“挽回夕小瑶”的任务卡进了隐马尔可夫模型&#xff08;HMM&#xff09;中。那么我们来规范化的整理一下已经有的信息和需要计算得到的信息。还记得这两个图嘛&#xff1f;这就是我们建立好的模型。&#xff08;隐状态的转移图&#x…

史上最简单的隐马尔可夫模型讲解

如果... 如果...有一天...你追到了女神夕小瑶...并且与她恋爱了... &#xff08;想说“没有如果”的路人请选择狗带(&#xffe3;∇&#xffe3;)&#xff09; 小夕的生活很规律的哦&#xff0c;小夕每天都会依次经历且仅仅经历以下6件事情&#xff1a; 化妆-吃饭-聊天-自习-上…

睡着了也在学习!Nature最新研究揭示运动记忆从何而来

来源&#xff1a;生物通Steph Curry罚球时&#xff0c;他的大脑会利用运动记忆。现在&#xff0c;加州大学旧金山分校(UCSF)的研究人员已经展示了这种类型的记忆是如何在睡眠期间得到巩固的&#xff0c;当大脑处理白天的学习&#xff0c;使做某事的物理行为成为潜意识时。Karun…

数据结构:堆(Heap)

数据结构&#xff1a;堆&#xff08;Heap&#xff09; <!-- 文章内容 --><div data-note-content"" class"show-content"><div class"show-content-free"><p>堆就是用数组实现的二叉树&#xff0c;所有它没有使用父指针…

BAT机器学习面试1000题系列

1、本文的内容全部来源于七月在线发布的BAT机器学习面试1000题系列&#xff1b; 2、文章中带斜体的文字代表是本人自己增加的内容&#xff0c;如有错误还请批评指正&#xff1b; 3、原文中有部分链接已经失效&#xff0c;故而本人重新加上了新的链接&#xff0c;如有不当&…

拉马努金:“与神对话”的数学天才

来源&#xff1a;微信公众号“图灵教育”撰文&#xff1a;[英] 马库斯杜索托伊翻译&#xff1a;柏华元当哈代和利特尔伍德步履维艰地穿越陌生的黎曼图景时&#xff0c;在5000英里外的印度马德拉斯港务局内&#xff0c;一个名叫斯里尼瓦瑟拉马努金的年轻办事员被素数的神秘莫测吸…

浅入深出被人看扁的逻辑回归!

好像在各种机器学习入门教程中&#xff0c;逻辑回归模型&#xff08;Logistic/Logit Regression&#xff09;经常被拿来作为入门的机器学习模型&#xff0c;比如我家的Andrew Ng就是这样做的。看起来&#xff0c;逻辑回归模型实在太简单&#xff0c;甚至容易被认为是一个拍脑袋…

全球Web3技术产业生态发展报告(2022年)

来源&#xff1a;中国信息通信研究院编辑&#xff1a;蒲蒲Web3不只是互联网应用层的简单创新&#xff0c;可能会带来互联网体系架构整体性演进和系统性升级。党中央、国务院高度关注下一代互联网创新发展&#xff0c;在关键核心技术突破、新型基础设施建设、融合创新应用赋能等…

算法工程师笔试 -剑指offer-习题详细解答

说明 主要编程语言为 C/C涉及字符串的问题可能会使用 Python题目编号以原书为准&#xff0c;如“面试题 3&#xff1a;数组中重复的数字” 因为题目不多&#xff0c;所以就不做分类了 所有代码均通过 OJ 测试 在线 OJ 地址&#xff1a;剑指Offer_编程题 - 牛客网 Reference 《…

深入深出Sigmoid与Softmax的血缘关系

缘起逻辑回归逻辑回归模型是用于二类分类的机器学习模型&#xff08;不要说逻辑回归可以做多类分类啊喂&#xff0c;那是二类分类器的组合策略问题&#xff0c;而与逻辑回归分类器本身的构造没有半毛钱关系啊&#xff09;。我们知道&#xff0c;在逻辑回归中&#xff0c;用于预…

科学家使用机器学习获得前所未有的小分子视图

编辑 | 绿萝数以千计的不同小分子&#xff08;称为代谢物&#xff09;在整个人体中传输能量和传递细胞信息。由于它们非常小&#xff0c;因此很难在血液样本分析中将代谢物彼此区分开来——但识别这些分子对于了解运动、营养、饮酒和代谢紊乱如何影响健康非常重要。尽管在过去十…

【Brain】脑洞从何而来?加州大学最新研究:有创造力的人神经连接会「抄近道」...

来源&#xff1a;量子位为什么有的人更富创造力&#xff1f;总能想到别人不会想到的东西&#xff0c;做别人想不到做的事&#xff1f;最近&#xff0c;这个问题的答案被找到了&#xff1a;有创造力的人&#xff0c;大脑里的神经活动会“抄近道”。加州大学洛杉矶分校的研究人员…

一位老师,一位领导,一个让全体学生考上目标学校的故事

今天&#xff0c;小夕给大家讲一个故事... 从前&#xff0c;有座山...​ 山里&#xff0c;有座学校... 学校里&#xff0c;有一位老师&#xff0c;一位领导&#xff0c;还有五只可爱的小仙(学)女(生)。 这5个学生的名字是&#xff1a;小兔&#xff0c;小青&#xff0c;小路&…

小冰李笛:ChatGPT在向“让你认为它有知识”的方向发展 | MEET 2023

来源&#xff1a;量子位衡宇 整理自 MEET2023ChatGPT技惊四座&#xff0c;甚至不少人认为它已经能“取代搜索引擎”。然而就在MEET2023智能未来大会上&#xff0c;却出现了这样一种迥然相异的观点&#xff1a;未来5年里&#xff0c;大家想要获取知识&#xff0c;最好的方法还是…

从前,有只小仙女叫...

从前&#xff0c;有只小仙女叫小音✧٩(ˊωˋ*)و✧这一篇真的不是小夕萌的技术文啦(&#xffe3;∇&#xffe3;)今天小夕给大家推送一点好玩的东西~毕竟高中老师说过&#xff0c;不能只学不玩嘛(&#xffe3;∇&#xffe3;)虽然小夕以萌著称\(//∇//)\&#xff0c;但是在da…

DeepMind新研究:AI也懂合纵连横

摘要人类文明的成功&#xff0c;植根于我们通过沟通和制定共同计划进行合作的能力。人工智能主体面临着与人类类似的问题。最近&#xff0c;人工智能公司 DeepMind 展示了AI如何利用沟通在桌游“强权外交”中更好地合作。研究发现&#xff0c;沟通主体容易受到背叛协议者的负面…

从逻辑回归到神经网络

回顾小夕在文章《逻辑回归》中详细讲解了逻辑回归模型&#xff0c;又在《Sigmoid与Softmax》中详细讲解了Sigmoid的实际意义&#xff08;代表二类分类问题中&#xff0c;其中一个类别的后验概率&#xff09;。至此&#xff0c;我们已经比较透彻的理解了逻辑回归模型假设函数(也…

华为2019年校招(20届实习)机考题python版解答与思路(2019-3-13软件题)

试题为今天考试时记下&#xff0c;记于此仅做学习分享。侵删。 答案思路仅供参考&#xff0c;肯定有更优的办法&#xff01;第三题没解出来&#xff0c;欢迎大家评论提点&#xff01; 第一题&#xff1a; 这道题对输入做切分&#xff08;调用split()方法&#xff09;后&#xf…

语言模型生成了自然界不存在的蛋白质,图灵奖得主LeCun:蛋白质编程来了

来源&#xff1a;药学前沿进展Meta&#xff1a;设计蛋白质这件事&#xff0c;语言模型就能干。用机器学习去研究蛋白质结构预测&#xff0c;吸引了众多科技大厂、科研机构的目光纷纷投入其中&#xff0c;这期间&#xff0c;他们也产出了重要成果。如在 2021 年 《Science》的十…

神经网络中的偏置项b到底是什么?

前言很多人不明白为什么要在神经网络、逻辑回归中要在样本X的最前面加一个1&#xff0c;使得 X[x1,x2,…,xn] 变成 X[1,x1,x2,…,xn] 。因此可能会犯各种错误&#xff0c;比如漏了这个1&#xff0c;或者错误的将这个1加到WX的结果上&#xff0c;导致模型出各种bug甚至无法收敛。…