当前位置: 首页 > news >正文

网站备案要注意什么外贸网站怎么做谷歌搜索

网站备案要注意什么,外贸网站怎么做谷歌搜索,网络营销有哪些理论和方法,广州效果图设计公司遗传算法与深度学习实战#xff08;33#xff09;——WGAN详解与实现 0. 前言1. 训练生成对抗网络的挑战2. GAN 优化问题2.1 梯度消失2.2 模式崩溃 2.3 无法收敛3 Wasserstein GAN3.1 Wasserstein 损失3.2 使用 Wasserstein 损失改进 DCGAN 小结系列链接 0. 前言 原始的生成… 遗传算法与深度学习实战33——WGAN详解与实现 0. 前言1. 训练生成对抗网络的挑战2. GAN 优化问题2.1 梯度消失2.2 模式崩溃 2.3 无法收敛3 Wasserstein GAN3.1 Wasserstein 损失3.2 使用 Wasserstein 损失改进 DCGAN 小结系列链接 0. 前言 原始的生成对抗网络 (Generative Adversarial Network, GAN) 在训练过程中面临着模式坍塌和梯度消失等问题为了解决这些问题研究人员提出了大量的关键技术以提高GAN模型的整体稳定性并降低了上述问题出现的可能性。例如 WGAN (Wasserstein GAN) 和 WGAN-GP (Wasserstein GAN-Gradient Penalty) 等通过对原始生成对抗网络 (Generative Adversarial Network, GAN) 框架进行了细微调整就能够训练复杂 GAN。在本节中我们将学习 WGAN 与 WGAN-GP两者都对原始 GAN 框架进行了细微调整以改善图像生成过程的稳定性和质量。 1. 训练生成对抗网络的挑战 生成对抗网络 (Generative Adversarial Network, GAN) 需要平衡鉴别器和生成器之间的学习能力如果任何一个模型超越了另一模型则整个系统将会失败。由于鉴别器是单独训练的因此它有机会作为独立的图像识别模型但在实际应用中其性能往往不如专门为图像识别训练的模型。 虽然构建和训练 GAN 的目标是能够生成逼真的伪造样本但同时也能够得到强大的鉴别器区分给定数据集中的真实样本和伪造样本。鉴别器本质上是一个分类器可以识别给定数据集中真实样本与伪造样本之间的差异从而使模型能够重用为所用数据集的简单分类器。例如如果在面部图像数据集上训练 GAN则训练后的鉴别器可以用于将图像分类为面部图像或非面部图像。 构建和训练一个能够得到逼真图像的 GAN 是极其困难的在本节中我们将探讨训练 GAN 时的问题并将研究解决这些问题的策略。 2. GAN 优化问题 通常生成对抗网络 (Generative Adversarial Network, GAN) 训练的主要问题是使生成器和鉴别器有效地并行收敛到一个解。通常当生成图像中出现各种伪影时就表明模型遇到了问题在训练 GAN 时最常见的问题包括 梯度消失-如果鉴别器擅长识别伪造样本这通常会减少反馈给生成器的损失量。反过来减少的损失会降低应用于生成器的训练梯度并导致梯度消失模式崩溃-生成器可能会被困在不断生成相同输出的状态中不同输出间的变化很小。这是因为模型会记住能够骗过鉴别器的单一模式实质上过拟合了生成的输出无法收敛-如果生成器在训练过程中改进得太快会导致鉴别器崩溃并且基本上在真实或伪造图像之间进行随机猜测 了解这些问题以及出现这些问题的原因对于理解和训练 GAN 非常有用接下来我们将复现 GAN 中的这些问题。 2.1 梯度消失 为了复现生成器的梯度消失问题我们通常只需要调整鉴别器使用的优化器。另外网络架构也可能导致梯度消失问题但我们已经采取了批归一化、droput 等措施来解决这一问题。 设置鉴别器优化器使得鉴别器能更好地或非常好地识别伪造图像和真实图像。因此随着训练的进行虽然生成器的损失已经最小化但输出没有明显改善 gen_optimizer Adam(0.0002, 0.5) disc_optimizer Adam(.00000001, .5)训练输出如下图所示可以看到生成器由于梯度消失而出现的问题。判断GAN是否遇到此问题的两个主要指标是生成器损失和鉴别器对伪造图像的损失如图所示鉴别器对伪造品的损失在整个训练过程中保持在一个小范围内不变。对于生成器来说这会导致随着时间的推移损失的变化较小产生梯度消失的现象。 通常当我们观察到深度学习模型中出现梯度消失时需要检查模型架构并寻找可能导致梯度消失的部分。在生成器模型构建时我们使用了 ReLU 激活函数可以通过改变生成器的激活函数观察问题是否得到解决 model.add(Dense(128 * cs * cs, activationrelu, input_dimlatent_dim)) model.add(Reshape((cs, cs, 128))) model.add(UpSampling2D()) model.add(Conv2D(128, kernel_size3, paddingsame)) model.add(BatchNormalization(momentum0.8)) #model.add(Activation(relu)) model.add(LeakyReLU(alpha0.2)) model.add(UpSampling2D()) model.add(Conv2D(64, kernel_size3, paddingsame)) model.add(BatchNormalization(momentum0.8)) #model.add(Activation(relu)) model.add(LeakyReLU(alpha0.2)) model.add(Conv2D(channels, kernel_size3, paddingsame)) model.add(Activation(tanh))修改生成器激活函数后重新运行代码可以看到模型的改进很小。这是因为问题出在鉴别器上改变生成器的激活函数并无太大影响。解决 GAN 中梯度消失的常用方法是调整优化器或改变损失计算的方式。 2.2 模式崩溃 当 GAN 的输出几乎完全相同时则表示发生了模式崩溃这种情况下生成器只会学习一种或少量几种能够骗过鉴别器的输出。然后随着鉴别器的改进生成器只会在很小范围内变化以得到能够继续欺骗鉴别器的输出。 为了重现 GAN 中的模式崩溃问题设置鉴别器优化器使鉴别器以较高速率学习 gen_optimizer Adam(0.0002, 0.5) disc_optimizer Adam(.002, .9)))训练 GAN 25 个 epoch 后结果如下所示可以看到输出图像的模式崩溃。 克服模式崩溃的简单方法是选用合适的优化器也可以通过调整损失函数来解决这一问题。接下来我们使用一个非常简单的方法来缓解模式崩溃问题在标签中添加噪声。添加一个布尔型常量 ADD_NOISE用于控制是否添加噪声 if ADD_NOISE:fake_d np.random.sample(BATCH_SIZE) * 0.2valid_d np.random.sample(BATCH_SIZE) * 0.2 0.8valid_g np.ones((BATCH_SIZE, 1)) else:valid_d np.ones((BATCH_SIZE, 1))fake_d np.zeros((BATCH_SIZE, 1))valid_g np.ones((BATCH_SIZE, 1))添加噪声后训练 GAN 25 个 epoch 后结果如下所示可以看到虽然由于优化器的问题结果仍然不是很好但输出图像间已经有所变化。 可以看出只需将噪声添加到标签中就能够纠正模式崩溃问题。 2.3 无法收敛 无法收敛是 GAN 中的另一潜在问题可能是模式崩溃、梯度消失或优化不平衡的结果。因此我们可以相对容易地重现收敛失败的情况。 为了重现收敛失败的情况设置生成器优化器 disc_optimizer RMSprop(.00001) # convergence gen_optimizer RMSprop(.00001)下图显示了 GAN 生成器收敛失败的情况尽管鉴别器能够很好的收敛但生成器损失无法收敛。 纠正收敛问题有一个相对简单的方法是打破生成器和鉴别器训练之间的回合制交替训练可以通过允许生成器和鉴别器的训练彼此独立地进行循环来实现。 为了支持进行独立的迭代在训练循环中添加两个内部循环一个用于训练鉴别器另一个用于训练生成器。可以使用变量 CRITIC_ITS 控制鉴别器迭代的频率使用 GEN_ITS 控制生成器迭代的频率 CRITIC_ITS 5 GEN_ITS 10 for e in range(EPOCHS):for i in tqdm(range(batches)):for _ in range(CRITIC_ITS):idx np.random.randint(0, train_images.shape[0], BATCH_SIZE)imgs train_images[idx]noise np.random.normal(0, 1, (BATCH_SIZE, latent_dim))gen_imgs g.predict(noise)d_loss_real d.train_on_batch(imgs, valid_d)d_loss_fake d.train_on_batch(gen_imgs, fake_d)d_loss 0.5 * np.add(d_loss_real, d_loss_fake)for _ in range(GEN_ITS):g_loss gan.train_on_batch(noise, valid_g)将 CRITIC_ITS 的值设置为 5将 GEN_ITS 的值设置为10运行代码打破生成器和鉴别器之间紧密依赖关系后的 GAN 收敛结果如下所示。 3 Wasserstein GAN WGAN (Wasserstein GAN) 是提高 GAN 训练稳定性方面的一次巨大进步在经过一些简单改动后 GAN 就能够实现以下两个特点: 与生成器的收敛度和生成样本质量相关的损失度量优化过程的稳定性得到提高 具体来说WGAN 针对判别器和生成器提出了一种新的损失函数 (Wasserstein Loss)用这种损失函数代替二元交叉熵就可以让 GAN 的收敛更加稳定。 3.1 Wasserstein 损失 首先我们来回顾一下二元交叉嫡, 在训练 DCGAN 判别器和生成器时采用以下损失函数 − 1 n ∑ i 1 n ( y i l o g ( p i ) ( 1 − y i ) l o g ( 1 − p i ) ) -\frac 1 n \sum_{i1}^n(y_ilog(p_i)(1-y_i)log(1-p_i)) −n1​i1∑n​(yi​log(pi​)(1−yi​)log(1−pi​)) 为了训练 GAN 的判别器 D我们根据以下两者计算损失真实图像的预测 p i D ( x i ) p_iD(x_i) pi​D(xi​) 与标签 y i 1 y_i1 yi​1 之间的误差以及生成图像的预测 p i D ( G ( z i ) ) p_iD(G(z_i)) pi​D(G(zi​))与标签 y i 0 y_i0 yi​0 之间的误差。因此对于 GAN 的判别器来说损失函数最小化的过程可以表示为: min ⁡ D − ( E x ∼ p X [ log ⁡ D ( x ) ] E z ∼ p Z [ log ⁡ ( 1 − D ( G ( z ) ) ) ] ) \mathop {\min} \limits_{D}-(\mathbb E_{x\sim p_X}[\log D(x)]\mathbb E_{z\sim p_Z}[\log (1-D(G(z)))]) Dmin​−(Ex∼pX​​[logD(x)]Ez∼pZ​​[log(1−D(G(z)))]) 为了训练 GAN 的生成器 G我们根据生成图像的预测 p i D ( G ( z i ) ) p_iD(G(z_i)) pi​D(G(zi​)) 与标签 y i 1 y_i1 yi​1 的误差计算损失。因此对于 GAN 的生成器来说将损失函数最小化的过程可以表示为: min ⁡ G − ( E z ∼ p Z [ log ⁡ D ( G ( z ) ) ] ) \mathop {\min}\limits_{G}-(\mathbb E_{z\sim p_Z}[\log D(G(z))]) Gmin​−(Ez∼pZ​​[logD(G(z))]) 接下来我们比较上述损失函数与 Wasserstein 损失函数。 Wasserstein 损失 (Wasserstein Loss) 是用于 Wasserstein GAN (WGAN) 的一种损失函数。与传统的二元交叉熵损失函数不同Wasserstein 损失引入了标签 1 和 -1将判别器的输出从概率值转变为分数 (score)因此WGAN 的判别器通常也被称为评论家 (critic)并要求判别器是 1-Lipschitz 连续函数。 具体来说Wasserstein 损失使用标签 y i 1 y_i1 yi​1 和 y i − 1 y_i-1 yi​−1 代替 y i 1 y_i1 yi​1 和 y i 0 y_i0 yi​0同时还需要移除判别器最后一层的 Sigmoid激活函数如此一来预测结果 p i p_i pi​ 就不一定在 [ 0 , 1 ] [0,1] [0,1] 范围内了它可以是 [ − ∞ , ∞ ] [-∞,∞] [−∞,∞] 范围内的任何值。Wasserstein 损失的定义如下 − 1 n ∑ i 1 n ( y i p i ) -\frac 1 n∑_{i1}^n(y_ip_i) −n1​i1∑n​(yi​pi​) 在训练 WGAN 的判别器 D 时我们将计算以下损失判别器对真实图像的预测 p i D ( x i ) p_iD(x_i) pi​D(xi​) 与标签 y i 1 y_i1 yi​1 之间的误差判别器对生成图像的预测 p i D ( G ( z i ) ) p_iD(G(z_i)) pi​D(G(zi​)) 与标签 y i − 1 y_i-1 yi​−1 之间的误差。因此对于 WGAN 判别器最小化损失函数的过程可以表示为 min ⁡ D − ( E x ∼ p X [ D ( x ) ] − E z ∼ p Z [ D ( G ( z ) ) ] ) \mathop {\min}\limits_ D - (\mathbb E_{x\sim p_X}[D(x)] - \mathbb E_{z\sim p_Z}[D(G(z))]) Dmin​−(Ex∼pX​​[D(x)]−Ez∼pZ​​[D(G(z))]) 换句话说WGAN 判别器试图最大化其对真实图像的预测和生成图像的预测之间的差异且真实图像的得分更高。 而对于 WGAN 生成器 G 的训练我们根据判别器对生成图像的预测 p i D ( G ( z i ) ) p_iD(G(z_i)) pi​D(G(zi​)) 与标签 y i 1 y_i1 yi​1 计算损失。因此对于 WGAN 生成器最小化损失函数可以表示为 min ⁡ G − ( E z ∼ p Z [ D ( G ( z ) ) ] ) \mathop {\min}\limits_ G - (\mathbb E_{z\sim p_Z}[D(G(z))]) Gmin​−(Ez∼pZ​​[D(G(z))]) 换句话说WGAN 生成器试图生成被判别器以极高分数判定为真实图像的图像(即令判别器认为它们是真实的)。 3.2 使用 Wasserstein 损失改进 DCGAN 在本节中将介绍如何在 GAN 中实现 Wasserstein 距离损失代码构建在 DCGAN 之上在其中添加 Wassertein 损失。 (1) 首先导入所需库和数据集 from tensorflow.keras.datasets import mnist as data from tensorflow.keras.models import Sequential, Model from tensorflow.keras.layers import Input, Dense, Activation, Flatten, Reshape, Dropout, ZeroPadding2D from tensorflow.keras.layers import Conv2D, Conv2DTranspose, UpSampling2D, Convolution2D from tensorflow.keras.layers import BatchNormalization from tensorflow.keras.layers import LeakyReLU from tensorflow.keras.optimizers import Adam, RMSpropimport tensorflow.keras.backend as Kimport numpy as np import matplotlib.pyplot as plt from livelossplot import PlotLosses from tqdm import tqdm_notebookimport random from tqdm.notebook import tqdm as tqdm(train_images, train_labels), (test_images, test_labels) data.load_data()# split dataset #train_images train_images.reshape(train_images.shape[0], 28, 28, 1).astype(float32) / 255.0 print(train_images.shape)# Rescale -1 to 1 train_images (train_images.astype(np.float32) - 127.5) / 127.5 train_images np.expand_dims(train_images, axis3) print(train_images.shape)def extract(images, labels, class_):idx labels class_print(idx)imgs images[idx]print(imgs.shape)return imgstrain_images extract(train_images, train_labels, 5)(2) 实例化优化器将鉴别器模型的名称更改为评论家 critic这是因为评论家预测真实性或虚假性的量度而不是真实或虚假的概率生成器和评论家使用相同的优化器。我们之所以能够这样做也是因为各项度量之间的差异被归一化了 latent_dim 100gen_optimizer RMSprop(lr0.00005) critic_optimizer RMSprop(lr0.00005)(3) 使用 wasserstein_loss() 函数计算 Wasserstein 损失。将真实输入的平均值与预测值相乘输出两个分布之间的 Wasserstein 距离 def wasserstein_loss(y_true, y_pred): return K.mean(y_true * y_pred)cs int(train_images.shape[1] / 4) print(train_images.shape) channels train_images.shape[3] img_shape (train_images.shape[1], train_images.shape[2], channels)然后在评论家模型编译时使用 wasserstein_loss 函数。 (4) 更新评论家训练代码。Wasserstein 损失引入了爆炸梯度的可能性为了解决这一问题添加权重裁剪步骤对于评论家的每个训练迭代确保将每个模型权重裁剪到 clip_value 超参数内。这种权重剪切消除了可能出现的爆炸梯度并降低了收敛模型空间 def build_generator():model Sequential()model.add(Dense(128 * cs * cs, activationrelu, input_dimlatent_dim))model.add(Reshape((cs, cs, 128)))model.add(UpSampling2D())model.add(Conv2D(128, kernel_size3, paddingsame))model.add(BatchNormalization(momentum0.8))model.add(Activation(relu))model.add(UpSampling2D())model.add(Conv2D(64, kernel_size3, paddingsame))model.add(BatchNormalization(momentum0.8))model.add(Activation(relu))model.add(Conv2D(channels, kernel_size3, paddingsame))model.add(Activation(tanh))model.summary()noise Input(shape(latent_dim,))img model(noise)return Model(noise, img) g build_generator()def build_critic():model Sequential()model.add(Conv2D(32, kernel_size3, strides2, input_shapeimg_shape, paddingsame))model.add(LeakyReLU(alpha0.2))model.add(Dropout(0.25))model.add(Conv2D(64, kernel_size3, strides2, paddingsame))model.add(ZeroPadding2D(padding((0,1),(0,1))))model.add(BatchNormalization(momentum0.8))model.add(LeakyReLU(alpha0.2))model.add(Dropout(0.25))model.add(Conv2D(128, kernel_size3, strides2, paddingsame))model.add(BatchNormalization(momentum0.8))model.add(LeakyReLU(alpha0.2))model.add(Dropout(0.25))model.add(Conv2D(256, kernel_size3, strides1, paddingsame))model.add(BatchNormalization(momentum0.8))model.add(LeakyReLU(alpha0.2))model.add(Dropout(0.25))model.add(Flatten())model.add(Dense(1))model.summary()img Input(shapeimg_shape)validity model(img)return Model(img, validity)critic build_critic() critic.compile(losswasserstein_loss,optimizercritic_optimizer,metrics[accuracy])(5) 在 MNIST 手写数字数据集的单个类别上训练 80 个 epoch结果如下图所示。还可以删除对 extract() 函数的调用以查看模型在数据集的所有类别中的表现 z Input(shape(latent_dim,)) img g(z)# For the combined model we will only train the generator critic.trainable False# The discriminator takes generated images as input and determines validity valid critic(img)# The combined model (stacked generator and discriminator) # Trains the generator to fool the discriminator gan Model(z, valid) gan.compile(losswasserstein_loss, optimizergen_optimizer)def plot_generated(n_ex10, dim(1, 10), figsize(12, 2)):noise np.random.normal(0, 1, size(n_ex, latent_dim))generated_images g.predict(noise)generated_images generated_images.reshape(n_ex, img_shape[0], img_shape[1])plt.figure(figsizefigsize)for i in range(generated_images.shape[0]):plt.subplot(dim[0], dim[1], i1)plt.imshow((1-generated_images[i])*255, interpolationnearest, cmapgray_r)plt.axis(off)plt.tight_layout() plt.show()EPOCHS 75 #param {type:slider, min:5, max:100, step:1} BATCH_SIZE 256 #param {type:slider, min:64, max:256, step:2} CRITIC_ITS 5 #param {type:slider, min:1, max:10, step:1}clip_value .01groups { Critic : {Real, Fake}, Generator:{Gen}} plotlosses PlotLosses(groupsgroups)plt_frq 1 batches int(train_images.shape[0] / BATCH_SIZE)# Adversarial ground truths valid -np.ones((BATCH_SIZE, 1)) fake np.ones((BATCH_SIZE, 1))for e in range(EPOCHS):for i in tqdm(range(batches)):for _ in range(CRITIC_ITS):# Train Critic# Select a random half of imagesidx np.random.randint(0, train_images.shape[0], BATCH_SIZE)imgs train_images[idx] # Sample noise and generate a batch of new imagesnoise np.random.normal(0, 1, (BATCH_SIZE, latent_dim))gen_imgs g.predict(noise)# Train the critic (real classified as ones and generated as zeros)c_loss_real critic.train_on_batch(imgs, valid)c_loss_fake critic.train_on_batch(gen_imgs, fake)c_loss 0.5 * np.add(c_loss_real, c_loss_fake) #clip critic weightsfor l in critic.layers:weights l.get_weights()weights [np.clip(w, -clip_value, clip_value) for w in weights]l.set_weights(weights) # Train Generatorg_loss gan.train_on_batch(noise, valid) loss dict(Real c_loss[0], Fake c_loss[1], Gen g_loss) plotlosses.update(loss)plotlosses.send()plot_generated()将 Wasserstein 损失引入 DCGAN 消除了标准 GAN 的几个问题使我们更容易构建最佳 GAN。 小结 WGAN 是 GAN 的一种变体通过使用 Wasserstein 距离来衡量生成样本与真实样本之间的差异。在本节中我们学习了如何使用 Wasserstein 损失函数以解决经典 GAN 训练过程中的模式坍塌和梯度消失等问题使得 GAN 的训练过程更加稳定和可靠。 系列链接 遗传算法与深度学习实战1——进化深度学习 遗传算法与深度学习实战2——生命模拟及其应用 遗传算法与深度学习实战3——生命模拟与进化论 遗传算法与深度学习实战4——遗传算法Genetic Algorithm详解与实现 遗传算法与深度学习实战5——遗传算法中常用遗传算子 遗传算法与深度学习实战6——遗传算法框架DEAP 遗传算法与深度学习实战7——DEAP框架初体验 遗传算法与深度学习实战8——使用遗传算法解决N皇后问题 遗传算法与深度学习实战9——使用遗传算法解决旅行商问题 遗传算法与深度学习实战10——使用遗传算法重建图像 遗传算法与深度学习实战11——遗传编程详解与实现 遗传算法与深度学习实战12——粒子群优化详解与实现 遗传算法与深度学习实战13——协同进化详解与实现 遗传算法与深度学习实战14——进化策略详解与实现 遗传算法与深度学习实战15——差分进化详解与实现 遗传算法与深度学习实战16——神经网络超参数优化 遗传算法与深度学习实战17——使用随机搜索自动超参数优化 遗传算法与深度学习实战18——使用网格搜索自动超参数优化 遗传算法与深度学习实战19——使用粒子群优化自动超参数优化 遗传算法与深度学习实战20——使用进化策略自动超参数优化 遗传算法与深度学习实战21——使用差分搜索自动超参数优化 遗传算法与深度学习实战22——使用Numpy构建神经网络 遗传算法与深度学习实战23——利用遗传算法优化深度学习模型 遗传算法与深度学习实战24——在Keras中应用神经进化优化 遗传算法与深度学习实战25——使用Keras构建卷积神经网络 遗传算法与深度学习实战26——编码卷积神经网络架构 遗传算法与深度学习实战27——进化卷积神经网络 遗传算法与深度学习实战28——卷积自编码器详解与实现 遗传算法与深度学习实战29——编码卷积自编码器架构 遗传算法与深度学习实战30——使用遗传算法优化自编码器模型 遗传算法与深度学习实战31——变分自编码器详解与实现 遗传算法与深度学习实战32——生成对抗网络详解与实现
http://www.dnsts.com.cn/news/212713.html

相关文章:

  • 成都网站建设福州市北区网站建设
  • 如何建设手机版网站asp网站开发实例pdf
  • 副业做网站软件wordpress博客建站
  • 免费查看招标信息的网站漳州网站建设求职简历
  • 销售培训网站优化检查
  • 扶绥县住房和城乡建设局网站网站建设公司大全
  • 黄山网站开发jidela如何建设网站简答题
  • 网站建设优化需要懂那些知识怎么配置wordpress
  • 旅游网站系统设计大连 模板网站
  • 如何做网站的自由撰稿人ip上海官网
  • 做网站都是花钱吗上海外贸50强企业
  • 谷城做网站wordpress支付宝免签约
  • 网站域名如何从代理商那里转出来网站文章列表如何排版
  • 个人网站名可以和别人一样吗徐州有哪些做网站
  • 佛山市网站建设公司成都必去的地方排行榜
  • 佛山建网站公司哪家好WordPress调用内部js
  • 网站外部链接如何建设温州公司建设网站
  • 海口澄迈县建设局网站wordpress 修改语言
  • 织梦网做网站步骤营销网络和网络营销的区别
  • 嘉兴型网站系统总部网站排名查询
  • 571免费建网站赤壁网站设计
  • 网站上传权限国际设计师网站
  • 什么是网站后台建设电子网站建设方案
  • 阿里巴巴国际站下载什么游戏不用登录直接玩
  • 餐饮商家做网站的好处关于优化培训
  • 芜湖网站7天精通网站建设实录
  • 东莞网站建设渠道长沙微信网站开发
  • 网站开发合同下载建设网站需要哪些东西
  • 笨鸟网站开发高级设计师培训班
  • 开封网站建设培训学校挂甲寺网站建设