GAN生成对抗网络基本概念及基于mnist数据集的代码实现

本文主要总结了GAN(Generative Adversarial Networks) 生成对抗网络的基本原理并通过mnist数据集展示GAN网络的应用。

GAN网络是由两个目标相对立的网络构成的,在所有GAN框架中都至少包含了两个部分,生成模型部分和判别模型部分。生成模型的目标是制造出一些与真实数据十分相似的伪造数据而判别模型的目标则恰恰相反,是找到如何分辨这些真实的数据以及伪造数据。

下图可以用来比较简明地理解GAN的工作原理 :
在这里插入图片描述
生成模型的输入是随机的噪声编码zzz,通过这个噪声生成的数据 G(z)G(z)G(z) 就是我们伪造出的数据了。判别模型的输入是一组混合了真实数据xxx以及伪造的数据G(z)G(z)G(z)的混合数据并输出D(G(z))D(G(z))D(G(z)) 以及D(x)D(x)D(x),代表了对真实数据和伪造数据的判定。如果我们把伪造数据的标签定为0,真实数据的标签定为1,那么判别模型的训练目标就是使D(G(z))D(G(z))D(G(z))无限接近0,使D(x)D(x)D(x)无限接近1,以此来达到分辨真实数据和伪造数据的目的。相反的,生成模型的训练目标则是要使得D(G(z))D(G(z))D(G(z))接近1,即达到欺骗判别模型,以假乱真的目的。我们不难发现,实际生成模型的训练离不开判别模型的判定,而判别模型的训练也需要生成模型生成的伪造数据,二者相辅相成。这一点在下面基于mnist数据集的训练代码中也会有所体现。

首先是import所需库并导入mnist数据,我们通过全部除以255的方法正则化用于训练和测试的图像。

import tensorflow as tf
from tensorflow import keras
from matplotlib import pyplot as plt
from keras.layers import Dense, Conv2DTranspose, BatchNormalization, Reshape, LeakyReLU, Conv2D
import numpy as np# load data from database mnist
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data(path="mnist.npz")# normaliser à [0,1]
x_train = x_train/255.0
x_test = x_test/255.0

训练集x_train中包含了60000张 28*28的单通道灰度图片,每张图片对应标签为0-9的十个数字,下面展示其中一张代表了数字5的图片。
在这里插入图片描述

1. 生成模型部分

首先是我们的生成模型,如上所说,生成模型的输入为随机噪声,输出为伪造的数据。在这个例子中,我们最终要输出一张与真实图片大小一致的灰度图。生成模型由两类主要的层构成,其中之一就是全连接层dense,这个层实际上类似于CNN卷积神经网络中代表特征 feature 的一层,我们可以理解为它由数个低解析度的图像组成。之后需要的就是将解析度提升至的操作,这里用了Conv2DTranspose层,可以理解为是一个反向的pooling池化层(用于还原参数和数据)和一个2D卷积层的结合。Conv2DTranspose层中的参数stride设置为(2, 2) 即保证了每经过一次该层,输出的宽度和高度都扩大一倍。如下例所示,由7 * 7 经过两次Conv2DTranspose层使得最终输出的灰度图宽度和高度为 28 * 28 。生成模型的输出层是一个简单的2D卷积层,使用activation激励函数为sigmoid,这是由于sigmoid函数可以使得输出值属于[0, 1]的区间,也对应了我们在一开始在数据预处理的时候,将数据正则化至[0, 1]的操作。

# creation of a generator
def creation_generateur(dim_latent=10):generator = keras.models.Sequential()generator.add(Dense(128*7*7, input_dim=dim_latent))generator.add(Reshape((7,7,128)))# upsampling generator.add(Conv2DTranspose(filters=128,kernel_size=(5,5),strides=(2,2),padding="same"))generator.add(LeakyReLU(alpha=0.2))# upsampling generator.add(Conv2DTranspose(filters=128,kernel_size=(5,5),strides=(2,2),padding="same"))generator.add(LeakyReLU(alpha=0.2))generator.add(Conv2D(1, kernel_size=(7, 7), activation='sigmoid', padding="same"))return generator

2. 判别模型部分

接着我们创建GAN中的判别模型,相比生成模型而言,判别模型就更加简明,其实质就是一个classifier二元分类器。他由多个卷积层构成,其中添加了drop out用于防止过拟合。输出层是一个仅有一个神经元的全连接层,使用sigmoid作为激励函数。正如我们前文所提到的,判别模型会对输入进行分类,判别输入究竟是真实图像还是由生成模型伪造的图像。

# creation of a discriminator
def creation_discriminateur():discriminator = keras.models.Sequential()discriminator.add(Conv2D(filters=64, kernel_size=(5,5),strides=(2,2), input_shape=(28,28,1), padding="same")) discriminator.add(LeakyReLU(alpha=0.2))discriminator.add(keras.layers.Dropout(0.4))discriminator.add(Conv2D(filters=64, kernel_size=(3,3),strides=(2,2), padding="same"))discriminator.add(LeakyReLU(alpha=0.2))discriminator.add(keras.layers.Dropout(0.4))discriminator.add(keras.layers.Flatten())discriminator.add(keras.layers.Dense(1,activation='sigmoid'))return discriminator

3. 叠加模型(用于训练生成模型)

有了上述两部分代码,接下来我们可以构建基于生成模型部分以及判别模型部分的GAN神经网络。这里我们只是将两部分叠加起来,而并非构建第三个神经网络。这里构建GAN的方式与之后训练GAN是有关系的。如下代码所示,我们将生成模型与判别模型叠加起来,并让判别模型中的参数在该模型中不可训练。其实质是因为这个叠加模型GAN是用于训练生成模型的。整体的过程如下 : 输入是一组随机噪声,经过生成模型后变成了一组伪造的数字灰度图,再经过判别模型,输出一个0-1之间的值。这是梯度的正向传播过程。接着我们利用反向梯度传播来更新我们生成模型的各个权重,以此来达到使该叠加模型输出趋向于1。 这里其实就是GAN模型训练的重中之重,即生成模型的目标与判别模型相反,其目标为生成的伪造数据能更大概率被识别为是真实数据,即标签1。这一点在下一个部分GAN模型的训练中会更详细解释。

def creation_reseau_GAN(model_generateur, model_discriminateur):GAN = keras.models.Sequential()GAN.add(model_generateur)# 判别模型中的参数设置为不可训练discriminateur.trainable = FalseGAN.add(model_discriminateur)optimizer_GAN = keras.optimizers.Adam(learning_rate=0.0002, beta_1=0.5)GAN.compile(loss='binary_crossentropy', optimizer=optimizer_GAN)return GAN

4. GAN模型的训练过程

根据上述三个部分,我们创建完毕了所要用到的神经网络。在这个部分中我们就进入GAN模型的训练过程。

首先我们要给予生成模型一组随机噪声,以便其根据这个噪声创造不同的伪造数据,该噪声的意义在于避免所有的生成数据都是一样的。可以用高斯噪声或正态分布生成噪声,不同的噪声类型选取对模型训练的影响不大。

# 随机选取潜在编码(噪声)
def code_latent_aleatoire(dim_latent, nb_exemples):# distribution normal standard normal distribution# code_latent = np.random.normal(loc=0, scale=1, size=(nb_exemples, dim_latent))# code_latent = code_latent.reshape(nb_exemples, dim_latent)code_latent = np.random.randn(nb_exemples, dim_latent)return code_latent

为了判别模型的训练,我们同时需要真实的数据和伪造的数据,因此我们定义函数用于根据现有的生成模型和随机噪声来生成伪造图片,伪造图片的标签为0。同样的,定义另一个函数,用于在mnist数据中随机选取真实图片,真实图片的标签为1。

def construction_image_generateur(generateur_model, dim_latent, nb_exemples):# 生成随机噪声X = code_latent_aleatoire(dim_latent,nb_exemples)image_fraud = generateur_model.predict(X)# 生成的图片的真实标签为0Label_genere = np.zeros((nb_exemples,1))return image_fraud, Label_generedef tirage_reelle_aleatoire(base_de_donnees, nb_exemples):mat_images_reel = np.zeros((nb_exemples, 28, 28))for i in range(nb_exemples):index = np.random.randint(0, base_de_donnees.shape[0])mat_images_reel[i,:,:] = base_de_donnees[index,:,:]mat_images_reel = mat_images_reel.reshape(nb_exemples, 28, 28, 1)# 从mnist数据集选取的图片的标签均为1labels_reel = np.ones((nb_exemples, 1))return mat_images_reel, labels_reel

接下来就是重头戏,GAN网络的训练过程了。要训练一个gan模型,我们常用的方法是利用train_on_batch函数来训练。在每个batch中,首先训练判别模型,我们先构建一组由真实数据和伪造数据组成的数据集,训练判别模型使其能更准确分辨哪些数据是真实的而哪些数据是伪造的。紧接着在同一个batch中,训练叠加模型,通过随机噪声进入生成模型去生成伪造的图片,并给予他们一个假的标签,即所有的伪造图片我们都标为1,以此来使得生成模型向着使判别模型判定伪造图片为真的方向进行。

# GAN 模型的训练
def entrainement_GAN_model(model_generateur, model_discriminateur, base_de_donnees, dim_latent, GAN_model, epochs=20, batch_size=128):vector_loss_discriminateur = []vector_loss_gan = []# 通过数据集的大小以及batchsize计算每个epoch对应的batch数量total_batch = np.floor(base_de_donnees.shape[0]/batch_size).astype(np.int)# 对于每个epochfor nb_epoch in range(epochs):# 对于每个batchfor index_batch in range(total_batch):# 每个batch中有一半的图像为伪造图片x_fraud, y_fraud = construction_image_generateur(model_generateur, dim_latent=dim_latent, nb_exemples=int(batch_size/2))# 剩下的图像为真实的从mnist数据集中随机提取的图片x_reel, y_reel = tirage_reelle_aleatoire(base_de_donnees=base_de_donnees, nb_exemples=int(batch_size/2))# 叠加所有的数据 id_exemple, 28, 28x_chaque_batch = np.vstack((x_reel, x_fraud))# 叠加所有的标签 : id_exemple, labely_chaque_batch = np.vstack((y_reel, y_fraud))# 使用构建的一半真实一半伪造的数据训练判别模型,更新权重。loss_discriminateur = model_discriminateur.train_on_batch(x_chaque_batch, y_chaque_batch)# 接下来是每个Batch训练叠加模型的部分,其实质是用于训练生成模型。x_generateur = code_latent_aleatoire(dim_latent=dim_latent, nb_exemples=batch_size)# 这里我们要使得叠加模型的输出趋向于1,即使判别模型认为生成的图像也是真实的。y_gan = np.ones((batch_size,1))# 使用判别模型(叠加模型)的输出来训练生成模型gan_loss = GAN_model.train_on_batch(x_generateur, y_gan)# 显示每个batch对应的两个部分的lossprint("%d epochs,%d batches, loss_discriminateur : %f, loss_gan : %f"%(nb_epoch+1, index_batch+1, loss_discriminateur, gan_loss))# 保存模型以及图片部分if (nb_epoch + 1)%3 == 0:model_generateur.save("generateur_models/generateur_after_" + str(nb_epoch+1) + "_epoch_" + "loss_%3f"%(gan_loss) + ".h5")model_discriminateur.save("discriminateur_models/discriminateur_after_" + str(nb_epoch+1) + "_epoch_" + "loss_%3f"%(loss_discriminateur) + ".h5") GAN_model.save("gan_models/gan_after_" + str(nb_epoch+1) + "_epoch_" + "loss_%3f"%(gan_loss) + ".h5")generer_sauvegarde_images(model_generateur=model_generateur, after_epoch=nb_epoch)vector_loss_discriminateur.append(loss_discriminateur)vector_loss_gan.append(gan_loss)return vector_loss_discriminateur, vector_loss_gan

5. 附录(完整代码)及相关讨论

该部分中我将放出完整的代码以及结果。

import tensorflow as tf
from tensorflow import keras
from matplotlib import pyplot as plt
from keras.layers import Dense, Conv2DTranspose, BatchNormalization, Reshape, LeakyReLU, Conv2D
import numpy as np# creation of a generator
def creation_generateur(dim_latent=10):generator = keras.models.Sequential()generator.add(Dense(128*7*7, input_dim=dim_latent))generator.add(Reshape((7,7,128)))# upsampling generator.add(Conv2DTranspose(filters=128,kernel_size=(5,5),strides=(2,2),padding="same"))generator.add(LeakyReLU(alpha=0.2))# upsampling generator.add(Conv2DTranspose(filters=128,kernel_size=(5,5),strides=(2,2),padding="same"))generator.add(LeakyReLU(alpha=0.2))generator.add(Conv2D(1, kernel_size=(7, 7), activation='sigmoid', padding="same"))return generator# creation of a discriminator
def creation_discriminateur():discriminator = keras.models.Sequential()discriminator.add(Conv2D(filters=64, kernel_size=(5,5),strides=(2,2), input_shape=(28,28,1), padding="same")) discriminator.add(LeakyReLU(alpha=0.2))discriminator.add(keras.layers.Dropout(0.4))discriminator.add(Conv2D(filters=64, kernel_size=(3,3),strides=(2,2), padding="same"))discriminator.add(LeakyReLU(alpha=0.2))discriminator.add(keras.layers.Dropout(0.4))discriminator.add(keras.layers.Flatten())discriminator.add(keras.layers.Dense(1,activation='sigmoid'))return discriminatordef creation_reseau_GAN(model_generateur, model_discriminateur):GAN = keras.models.Sequential()GAN.add(model_generateur)# 判别模型中的参数设置为不可训练discriminateur.trainable = FalseGAN.add(model_discriminateur)optimizer_GAN = keras.optimizers.Adam(learning_rate=0.0002, beta_1=0.5)GAN.compile(loss='binary_crossentropy', optimizer=optimizer_GAN)return GAN# 随机选取潜在编码(噪声)
def code_latent_aleatoire(dim_latent, nb_exemples):# distribution normal standard normal distribution# code_latent = np.random.normal(loc=0, scale=1, size=(nb_exemples, dim_latent))# code_latent = code_latent.reshape(nb_exemples, dim_latent)code_latent = np.random.randn(nb_exemples, dim_latent)return code_latentdef construction_image_generateur(generateur_model, dim_latent, nb_exemples):# 生成随机噪声X = code_latent_aleatoire(dim_latent,nb_exemples)image_fraud = generateur_model.predict(X)# 生成的图片的真实标签为0Label_genere = np.zeros((nb_exemples,1))return image_fraud, Label_generedef tirage_reelle_aleatoire(base_de_donnees, nb_exemples):mat_images_reel = np.zeros((nb_exemples, 28, 28))for i in range(nb_exemples):index = np.random.randint(0, base_de_donnees.shape[0])mat_images_reel[i,:,:] = base_de_donnees[index,:,:]mat_images_reel = mat_images_reel.reshape(nb_exemples, 28, 28, 1)# 从mnist数据集选取的图片的标签均为1labels_reel = np.ones((nb_exemples, 1))return mat_images_reel, labels_reel# 用于保存和显示图片的函数
def generer_sauvegarde_images(model_generateur,after_epoch,nb_images_sqrt=5,dim_latent=100):nb_images = nb_images_sqrt * nb_images_sqrtimages_frauds, _ = construction_image_generateur(model_generateur,dim_latent=dim_latent,nb_exemples=nb_images)for i in range(nb_images):plt.subplot(nb_images_sqrt, nb_images_sqrt, i+1)plt.imshow(images_frauds[i].reshape(28,28))filepath = "images_fraudes_genere_%d.png" %(after_epoch+1)plt.savefig(filepath)plt.close()# GAN 模型的训练
def entrainement_GAN_model(model_generateur, model_discriminateur, base_de_donnees, dim_latent, GAN_model, epochs=20, batch_size=128):vector_loss_discriminateur = []vector_loss_gan = []# 通过数据集的大小以及batchsize计算每个epoch对应的batch数量total_batch = np.floor(base_de_donnees.shape[0]/batch_size).astype(np.int)# 对于每个epochfor nb_epoch in range(epochs):# 对于每个batchfor index_batch in range(total_batch):# 每个batch中有一半的图像为伪造图片x_fraud, y_fraud = construction_image_generateur(model_generateur, dim_latent=dim_latent, nb_exemples=int(batch_size/2))# 剩下的图像为真实的从mnist数据集中随机提取的图片x_reel, y_reel = tirage_reelle_aleatoire(base_de_donnees=base_de_donnees, nb_exemples=int(batch_size/2))# 叠加所有的数据 id_exemple, 28, 28x_chaque_batch = np.vstack((x_reel, x_fraud))# 叠加所有的标签 : id_exemple, labely_chaque_batch = np.vstack((y_reel, y_fraud))# 使用构建的一半真实一半伪造的数据训练判别模型,更新权重。loss_discriminateur = model_discriminateur.train_on_batch(x_chaque_batch, y_chaque_batch)# 接下来是每个Batch训练叠加模型的部分,其实质是用于训练生成模型。x_generateur = code_latent_aleatoire(dim_latent=dim_latent, nb_exemples=batch_size)# 这里我们要使得叠加模型的输出趋向于1,即使判别模型认为生成的图像也是真实的。y_gan = np.ones((batch_size,1))# 使用判别模型(叠加模型)的输出来训练生成模型gan_loss = GAN_model.train_on_batch(x_generateur, y_gan)# 显示每个batch对应的两个部分的lossprint("%d epochs,%d batches, loss_discriminateur : %f, loss_gan : %f"%(nb_epoch+1, index_batch+1, loss_discriminateur, gan_loss))# 保存模型以及图片部分if (nb_epoch + 1)%3 == 0:model_generateur.save("generateur_models/generateur_after_" + str(nb_epoch+1) + "_epoch_" + "loss_%3f"%(gan_loss) + ".h5")model_discriminateur.save("discriminateur_models/discriminateur_after_" + str(nb_epoch+1) + "_epoch_" + "loss_%3f"%(loss_discriminateur) + ".h5") GAN_model.save("gan_models/gan_after_" + str(nb_epoch+1) + "_epoch_" + "loss_%3f"%(gan_loss) + ".h5")generer_sauvegarde_images(model_generateur=model_generateur, after_epoch=nb_epoch)vector_loss_discriminateur.append(loss_discriminateur)vector_loss_gan.append(gan_loss)return vector_loss_discriminateur, vector_loss_gan# load data from database mnist
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data(path="mnist.npz")
# normaliser à [0,1]
x_train = x_train/255.0
x_test = x_test/255.0
dim_code_latent = 100 
generateur = creation_generateur(dim_latent=dim_code_latent)
discriminateur = creation_discriminateur()
opt_discriminateur = keras.optimizers.Adam(learning_rate=0.0002, beta_1=0.5)
discriminateur.compile(loss=keras.losses.binary_crossentropy, optimizer=opt_discriminateur)
GAN = creation_reseau_GAN(generateur, discriminateur)
loss_discriminateur, loss_gan = entrainement_GAN_model(model_generateur=generateur, model_discriminateur=discriminateur,base_de_donnees=x_train, GAN_model=GAN, epochs=21, batch_size=256, dim_latent=dim_code_latent)

训练过后的生成模型就可以用来生成伪造图片,下图为经过9个epoch的训练后,所生成的伪造图片,我们可以发现生成的图像中已经有可以辨认出的数字,例如5,7,9。有理由认为我们在经过更多的epoch训练后,生成模型的细节将进一步完善。
在这里插入图片描述

小tips : 在训练GAN模型时,要时刻关注判别模型的loss以及accuracy。如果判别模型的loss下降的太快,这就意味着生成模型正在给我们生成一些垃圾数据,这些数据轻易地就被判别模型给判定为伪造了。一般而言,维持判别模型的loss在一定范围内会对整个GAN模型的训练有帮助。更进一步的说,一个完美的判别模型,即可以完美分辨真伪图片的判别模型不能给予生成模型足够的信息来产生合理的伪造图片,因此在训练的过程中时刻保持判别模型的非完美性是有必要的,这也增加了在处理更复杂问题时,GAN模型在调参方面的困难程度。

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

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

相关文章

dump查询Java 状态

代码文件 dump.sh #!/usr/bin/env bash### use demo ### # 1)upload dump.sh # 2)dos2unix dump.sh;chmod x dump.sh # 3)usage: # 1. /data/sh/java/dump.sh /tmp/dump /usr/local/java/jdk1.8.0_05 23554 # 2. /data/sh/java/dump.sh /tmp/dump /usr/local/java/jdk1…

jdk、jre、jvm区别与联系

JVM :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是…

autoencoder自编码器原理以及在mnist数据集上的实现

Autoencoder是常见的一种非监督学习的神经网络。它实际由一组相对应的神经网络组成(可以是普通的全连接层,或者是卷积层,亦或者是LSTMRNN等等,取决于项目目的),其目的是将输入数据降维成一个低维度的潜在编…

vscode编写插件详细过程

vscode编写插件详细过程 前言 之前编写了一个vscode插件用vscode写博客和发布,然后有园友要求写一篇来介绍如何开发一个vscode扩展插件,或者说介绍开发这个插件的过程。然而文章还没有写,园子里面已经有人发布一个文章,是园友上…

cannot find output in imported module librosa报错解决

librosa一直都是用处很广泛的python声音信号处理模块,但在最近的版本更新中,将原本的librosa.output给删去了。 为了代替之前的librosa.output.write_wav函数将音频写入wav文件中,现可以用模块soundfile代替。 soundfile.write(file, data, …

2018-2019-2 20175328 《Java程序设计》第十一周学习总结

十三章主要内容——Java网络编程 一、URL类 URL类是java.net包中的一个重要的类,URL的实例封装着一个统一资源定位符(Uniform Resource Locator),使用URL创建对象的应用程序称作客户端程序。 一个URL对象通常包含最基本的三部分信息:协议、地…

修改Header方法

/*** 修改header信息&#xff0c;key-value键值对儿加入到header中,如果存在&#xff0c;替换* param request* param key* param value*/ public static void reflectRequestParam(HttpServletRequest request, String key, String value){Class<? extends HttpServletReq…

pytorch学习笔记 1. pytorch基础 tensor运算

pytorch与tensorflow是两个近些年来使用最为广泛的机器学习模块。开个新坑记录博主学习pytorch模块的过程&#xff0c;不定期更新学习进程。 文章较为适合初学者&#xff0c;欢迎对代码和理解指点讨论&#xff0c;下面进入正题。 import torch import numpy as npt1 torch.te…

2019年区块链的主旋律是中间层协议

2019年区块链的主旋律是中间层协议 过去一年加密资产市场从其峰值下跌超过85%的市值。但对我&#xff0c;一个坚定的区块链企业家&#xff0c;这实际上是一件好事&#xff0c;区块链的未来看起来比以往任何时候都更有希望。2017年ICO热潮开始的疯狂至少产生了一个强烈的积极影响…

Java枚举的内容可以使用map的方式

枚举的内容可以使用map的方式 package com.chinamobile.framework.common.enums;import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import jav…

tensorflow gpu windows配置步骤教学

本文主要针对在windows10环境下的tensorflow配置问题&#xff0c;在linux和mac等其他环境中的配置就不过多赘述(windows总是那个问题最多的环境&#xff0c;建议使用linux &#x1f603;)。 本文中配置的环境为 python 3.8.5 tensorflow-gpu 2.4.1 1. 更新nvidia显卡驱动至最…

numpy一维数组永远为列向量

import numpy as np a np.array([1,3,4,5]) print(a.shape) a np.transpose(a) print(a.shape) print(a)a np.ravel(a) print(a.shape) print(a)a a.reshape((1,4)) print(a.shape)输出如下 (4,) (4,) [1 3 4 5] (4,) [1 3 4 5] (1, 4)我们会发现&#xff0c;对于一维的数…

【BJOI 2019】奥术神杖

题意 你有一个长度为 $n$ 的模板串&#xff08;由 $0-9$ 这 $10$ 个数字和通配符 $.$ 组成&#xff09;&#xff0c;还有 $m$ 个匹配串&#xff08;只由 $0-9$ 这 $10$ 个数字组成&#xff09;&#xff0c;每个匹配串有一个魔力值 $v_i$。你要把模板串的每个 $.$ 都换成一个数字…

keras模型中的默认初始化权重

权重的初始化&#xff0c;决定了模型训练的起点。一个良好的初始化可以加快训练过程&#xff0c;同时避免模型收敛至局部最小值。为了在训练过程中避免使得权重的变化总沿着同一个方向&#xff0c;我们尽量避免将所有权重都初始化为同一个值&#xff0c;如全0矩阵或全1矩阵。 …

java oracle的枚举错误

public enum OracleErrorTypeEnum implements BaseEnum {ORA00001("ORA-00001","不允许有重复的数据"),ORA00017("ORA-00017","请求会话以设置跟踪事件"),ORA00018("ORA-00018","超出最大会话数"),ORA00019(&quo…

C# 篇基础知识10——多线程

1.线程的概念 单核CPU的计算机中&#xff0c;一个时刻只能执行一条指令&#xff0c;操作系统以“时间片轮转”的方式实现多个程序“同时”运行。操作系统以进程&#xff08;Process&#xff09;的方式运行应用程序&#xff0c;进程不但包括应用程序的指令流&#xff0c;也包括运…

keras中mean square error均方误差理解

机器学习中&#xff0c;针对不同的问题选用不同的损失函数非常重要&#xff0c;而均方误差就是最基本&#xff0c;也是在解决回归问题时最常用的损失函数。本文就keras模块均方误差的计算梳理了一些细节。 首先看一下均方误差的数学定义 : 均方误差是预测向量与真实向量差值的…

Java并发Semaphore信号量的学习

public class MyThreadTest {private final static Semaphore semaphore new Semaphore(2);// 设置2个车位public static void main(String[] args) {System.out.println("start");p(semaphore, true, 1);p(semaphore, false, 2);p(semaphore, false, 3);p(semaphor…

快速理解binary cross entropy 二元交叉熵

Binary cross entropy 二元交叉熵是二分类问题中常用的一个Loss损失函数&#xff0c;在常见的机器学习模块中都有实现。本文就二元交叉熵这个损失函数的原理&#xff0c;简单地进行解释。 首先是二元交叉熵的公式 : Loss−1N∑i1Nyi⋅log⁡(p(yi))(1−yi)⋅log(1−p(yi))Loss …